'use strict'

var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? function(obj) { return typeof obj } : function(obj) { return obj && typeof Symbol === 'function' && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : typeof obj };

/*
 *  base64.js
 *
 *  Licensed under the BSD 3-Clause License.
 *    http://opensource.org/licenses/BSD-3-Clause
 *
 *  References:
 *    http://en.wikipedia.org/wiki/Base64
 */
(function(global) {
  'use strict'
  // existing version for noConflict()

  var _Base64 = global.Base64
  var version = '2.3.2'
  // if node.js, we use Buffer
  var buffer
  if (typeof module !== 'undefined' && module.exports) {
    try {
      buffer = require('buffer').Buffer
    } catch (err) {}
  }
  // constants
  var b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  var b64tab = (function(bin) {
    var t = {}
    for (var i = 0, l = bin.length; i < l; i++) {
      t[bin.charAt(i)] = i
    } return t
  }(b64chars))
  var fromCharCode = String.fromCharCode
  // encoder stuff
  var cb_utob = function cb_utob(c) {
    if (c.length < 2) {
      var cc = c.charCodeAt(0)
      return cc < 0x80 ? c : cc < 0x800 ? fromCharCode(0xc0 | cc >>> 6) + fromCharCode(0x80 | cc & 0x3f) : fromCharCode(0xe0 | cc >>> 12 & 0x0f) + fromCharCode(0x80 | cc >>> 6 & 0x3f) + fromCharCode(0x80 | cc & 0x3f)
    } else {
      var cc = 0x10000 + (c.charCodeAt(0) - 0xD800) * 0x400 + (c.charCodeAt(1) - 0xDC00)
      return fromCharCode(0xf0 | cc >>> 18 & 0x07) + fromCharCode(0x80 | cc >>> 12 & 0x3f) + fromCharCode(0x80 | cc >>> 6 & 0x3f) + fromCharCode(0x80 | cc & 0x3f)
    }
  }
  var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g
  var utob = function utob(u) {
    return u.replace(re_utob, cb_utob)
  }
  var cb_encode = function cb_encode(ccc) {
    var padlen = [0, 2, 1][ccc.length % 3]
		    var ord = ccc.charCodeAt(0) << 16 | (ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8 | (ccc.length > 2 ? ccc.charCodeAt(2) : 0)
		    var chars = [b64chars.charAt(ord >>> 18), b64chars.charAt(ord >>> 12 & 63), padlen >= 2 ? '=' : b64chars.charAt(ord >>> 6 & 63), padlen >= 1 ? '=' : b64chars.charAt(ord & 63)]
    return chars.join('')
  }
  var btoa = global.btoa ? function(b) {
    return global.btoa(b)
  } : function(b) {
    return b.replace(/[\s\S]{1,3}/g, cb_encode)
  }
  var _encode = buffer ? buffer.from && buffer.from !== Uint8Array.from ? function(u) {
    return (u.constructor === buffer.constructor ? u : buffer.from(u)).toString('base64')
  } : function(u) {
    return (u.constructor === buffer.constructor ? u : new buffer(u)).toString('base64')
  } : function(u) {
    return btoa(utob(u))
  }
  var encode = function encode(u, urisafe) {
    return !urisafe ? _encode(String(u)) : _encode(String(u)).replace(/[+\/]/g, function(m0) {
      return m0 == '+' ? '-' : '_'
    }).replace(/=/g, '')
  }
  var encodeURI = function encodeURI(u) {
    return encode(u, true)
  }
  // decoder stuff
  var re_btou = new RegExp(['[\xC0-\xDF][\x80-\xBF]', '[\xE0-\xEF][\x80-\xBF]{2}', '[\xF0-\xF7][\x80-\xBF]{3}'].join('|'), 'g')
  var cb_btou = function cb_btou(cccc) {
    switch (cccc.length) {
      case 4:
        var cp = (0x07 & cccc.charCodeAt(0)) << 18 | (0x3f & cccc.charCodeAt(1)) << 12 | (0x3f & cccc.charCodeAt(2)) << 6 | 0x3f & cccc.charCodeAt(3)
				    var offset = cp - 0x10000
        return fromCharCode((offset >>> 10) + 0xD800) + fromCharCode((offset & 0x3FF) + 0xDC00)
      case 3:
        return fromCharCode((0x0f & cccc.charCodeAt(0)) << 12 | (0x3f & cccc.charCodeAt(1)) << 6 | 0x3f & cccc.charCodeAt(2))
      default:
        return fromCharCode((0x1f & cccc.charCodeAt(0)) << 6 | 0x3f & cccc.charCodeAt(1))
    }
  }
  var btou = function btou(b) {
    return b.replace(re_btou, cb_btou)
  }
  var cb_decode = function cb_decode(cccc) {
    var len = cccc.length
		    var padlen = len % 4
		    var n = (len > 0 ? b64tab[cccc.charAt(0)] << 18 : 0) | (len > 1 ? b64tab[cccc.charAt(1)] << 12 : 0) | (len > 2 ? b64tab[cccc.charAt(2)] << 6 : 0) | (len > 3 ? b64tab[cccc.charAt(3)] : 0)
		    var chars = [fromCharCode(n >>> 16), fromCharCode(n >>> 8 & 0xff), fromCharCode(n & 0xff)]
    chars.length -= [0, 0, 2, 1][padlen]
    return chars.join('')
  }
  var atob = global.atob ? function(a) {
    return global.atob(a)
  } : function(a) {
    return a.replace(/[\s\S]{1,4}/g, cb_decode)
  }
  var _decode = buffer ? buffer.from && buffer.from !== Uint8Array.from ? function(a) {
    return (a.constructor === buffer.constructor ? a : buffer.from(a, 'base64')).toString()
  } : function(a) {
    return (a.constructor === buffer.constructor ? a : new buffer(a, 'base64')).toString()
  } : function(a) {
    return btou(atob(a))
  }
  var decode = function decode(a) {
    return _decode(String(a).replace(/[-_]/g, function(m0) {
      return m0 == '-' ? '+' : '/'
    }).replace(/[^A-Za-z0-9\+\/]/g, ''))
  }
  var noConflict = function noConflict() {
    var Base64 = global.Base64
    global.Base64 = _Base64
    return Base64
  }
  // export Base64
  global.Base64 = {
    VERSION: version,
    atob: atob,
    btoa: btoa,
    fromBase64: decode,
    toBase64: encode,
    utob: utob,
    encode: encode,
    encodeURI: encodeURI,
    btou: btou,
    decode: decode,
    noConflict: noConflict
  }
  // if ES5 is available, make Base64.extendString() available
  if (typeof Object.defineProperty === 'function') {
    var noEnum = function noEnum(v) {
      return { value: v, enumerable: false, writable: true, configurable: true }
    }
    global.Base64.extendString = function() {
      Object.defineProperty(String.prototype, 'fromBase64', noEnum(function() {
        return decode(this)
      }))
      Object.defineProperty(String.prototype, 'toBase64', noEnum(function(urisafe) {
        return encode(this, urisafe)
      }))
      Object.defineProperty(String.prototype, 'toBase64URI', noEnum(function() {
        return encode(this, true)
      }))
    }
  }
  //
  // export Base64 to the namespace
  //
  if (global['Meteor']) {
    // Meteor.js
    Base64 = global.Base64
  }
  // module.exports and AMD are mutually exclusive.
  // module.exports has precedence.
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define('Base64', [], function() {
      return global.Base64
    })
  }
  // that's it!
})(typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : undefined)

'use strict'; (function(Y) {
  function C(c, a, b) {
    var e = 0
		    var h = []
		    var n = 0
		    var g
		    var l
		    var d
		    var f
		    var m
		    var q
		    var u
		    var r
		    var I = !1
		    var v = []
		    var w = []
		    var t
		    var y = !1
		    var z = !1
		    var x = -1; b = b || {}; g = b.encoding || 'UTF8'; t = b.numRounds || 1; if (t !== parseInt(t, 10) || t < 1) throw Error('numRounds must a integer >= 1'); if (c === 'SHA-1') {
      m = 512, q = K, u = Z, f = 160, r = function r(a) {
        return a.slice()
      }
    } else if (c.lastIndexOf('SHA-', 0) === 0) {
      if (q = function q(a, b) {
        return L(a, b, c)
      }, u = function u(a, b, h, e) {
        var k, f; if (c === 'SHA-224' || c === 'SHA-256') k = (b + 65 >>> 9 << 4) + 15, f = 16; else if (c === 'SHA-384' || c === 'SHA-512') k = (b + 129 >>> 10 << 5) + 31, f = 32; else throw Error('Unexpected error in SHA-2 implementation'); for (; a.length <= k;) {
          a.push(0)
        }a[b >>> 5] |= 128 << 24 - b % 32; b = b + h; a[k] = b & 4294967295; a[k - 1] = b / 4294967296 | 0; h = a.length; for (b = 0; b < h; b += f) {
          e = L(a.slice(b, b + f), e, c)
        } if (c === 'SHA-224') a = [e[0], e[1], e[2], e[3], e[4], e[5], e[6]]; else if (c === 'SHA-256') a = e; else if (c === 'SHA-384') a = [e[0].a, e[0].b, e[1].a, e[1].b, e[2].a, e[2].b, e[3].a, e[3].b, e[4].a, e[4].b, e[5].a, e[5].b]; else if (c === 'SHA-512') a = [e[0].a, e[0].b, e[1].a, e[1].b, e[2].a, e[2].b, e[3].a, e[3].b, e[4].a, e[4].b, e[5].a, e[5].b, e[6].a, e[6].b, e[7].a, e[7].b]; else throw Error('Unexpected error in SHA-2 implementation'); return a
      }, r = function r(a) {
        return a.slice()
      }, c === 'SHA-224') m = 512, f = 224; else if (c === 'SHA-256') m = 512, f = 256; else if (c === 'SHA-384') m = 1024, f = 384; else if (c === 'SHA-512') m = 1024, f = 512; else throw Error('Chosen SHA variant is not supported')
    } else if (c.lastIndexOf('SHA3-', 0) === 0 || c.lastIndexOf('SHAKE', 0) === 0) {
      var F = 6; q = D; r = function r(a) {
        var c = []
				    var e; for (e = 0; e < 5; e += 1) {
          c[e] = a[e].slice()
        } return c
      }; x = 1; if (c === 'SHA3-224') m = 1152, f = 224; else if (c === 'SHA3-256') m = 1088, f = 256; else if (c === 'SHA3-384') m = 832, f = 384; else if (c === 'SHA3-512') m = 576, f = 512; else if (c === 'SHAKE128') m = 1344, f = -1, F = 31, z = !0; else if (c === 'SHAKE256') m = 1088, f = -1, F = 31, z = !0; else throw Error('Chosen SHA variant is not supported'); u = function u(a, c, e, b, h) {
        e = m; var k = F
				    var f
				    var g = []
				    var n = e >>> 5
				    var l = 0
				    var d = c >>> 5; for (f = 0; f < d && c >= e; f += n) {
          b = D(a.slice(f, f + n), b), c -= e
        }a = a.slice(f); for (c %= e; a.length < n;) {
          a.push(0)
        }f = c >>> 3; a[f >> 2] ^= k << f % 4 * 8; a[n - 1] ^= 2147483648; for (b = D(a, b); 32 * g.length < h;) {
          a = b[l % 5][l / 5 | 0]; g.push(a.b); if (32 * g.length >= h) break; g.push(a.a); l += 1; 64 * l % e === 0 && D(null, b)
        } return g
      }
    } else throw Error('Chosen SHA variant is not supported'); d = M(a, g, x); l = A(c); this.setHMACKey = function(a, b, h) {
      var k; if (!0 === I) throw Error('HMAC key already set'); if (!0 === y) throw Error('Cannot set HMAC key after calling update'); if (!0 === z) throw Error('SHAKE is not supported for HMAC'); g = (h || {}).encoding || 'UTF8'; b = M(b, g, x)(a); a = b.binLen; b = b.value; k = m >>> 3; h = k / 4 - 1; if (k < a / 8) {
        for (b = u(b, a, 0, A(c), f); b.length <= h;) {
          b.push(0)
        }b[h] &= 4294967040
      } else if (k > a / 8) {
        for (; b.length <= h;) {
          b.push(0)
        }b[h] &= 4294967040
      } for (a = 0; a <= h; a += 1) {
        v[a] = b[a] ^ 909522486, w[a] = b[a] ^ 1549556828
      }l = q(v, l); e = m; I = !0
    }; this.update = function(a) {
      var c
			    var b
			    var k
			    var f = 0
			    var g = m >>> 5; c = d(a, h, n); a = c.binLen; b = c.value; c = a >>> 5; for (k = 0; k < c; k += g) {
        f + m <= a && (l = q(b.slice(k, k + g), l), f += m)
      }e += f; h = b.slice(f >>> 5); n = a % m; y = !0
    }; this.getHash = function(a, b) {
      var k, g, d, m; if (!0 === I) throw Error('Cannot call getHash after setting HMAC key'); d = N(b); if (!0 === z) {
        if (d.shakeLen === -1) throw Error('shakeLen must be specified in options')
        f = d.shakeLen
      } switch (a) {
        case 'HEX':
          k = function k(a) {
            return O(a, f, x, d)
          }; break; case 'B64':
          k = function k(a) {
            return P(a, f, x, d)
          }; break; case 'BYTES':
          k = function k(a) {
            return Q(a, f, x)
          }; break; case 'ARRAYBUFFER':
          try {
            g = new ArrayBuffer(0)
          } catch (p) {
            throw Error('ARRAYBUFFER not supported by this environment')
          }k = function k(a) {
            return R(a, f, x)
          }; break; default:
          throw Error('format must be HEX, B64, BYTES, or ARRAYBUFFER')
      }m = u(h.slice(), n, e, r(l), f); for (g = 1; g < t; g += 1) {
        !0 === z && f % 32 !== 0 && (m[m.length - 1] &= 16777215 >>> 24 - f % 32), m = u(m, f, 0, A(c), f)
      } return k(m)
    }; this.getHMAC = function(a, b) {
      var k, g, d, p; if (!1 === I) throw Error('Cannot call getHMAC without first setting HMAC key'); d = N(b); switch (a) {
        case 'HEX':
          k = function k(a) {
            return O(a, f, x, d)
          }; break; case 'B64':
          k = function k(a) {
            return P(a, f, x, d)
          }; break; case 'BYTES':
          k = function k(a) {
            return Q(a, f, x)
          }; break; case 'ARRAYBUFFER':
          try {
            k = new ArrayBuffer(0)
          } catch (v) {
            throw Error('ARRAYBUFFER not supported by this environment')
          }k = function k(a) {
            return R(a, f, x)
          }; break; default:
          throw Error('outputFormat must be HEX, B64, BYTES, or ARRAYBUFFER')
      }g = u(h.slice(), n, e, r(l), f); p = q(w, A(c)); p = u(g, f, m, p, f); return k(p)
    }
  } function b(c, a) {
    this.a = c; this.b = a
  } function O(c, a, b, e) {
    var h = ''; a /= 8; var n, g, d; d = b === -1 ? 3 : 0; for (n = 0; n < a; n += 1) {
      g = c[n >>> 2] >>> 8 * (d + n % 4 * b), h += '0123456789abcdef'.charAt(g >>> 4 & 15) + '0123456789abcdef'.charAt(g & 15)
    } return e.outputUpper ? h.toUpperCase() : h
  } function P(c, a, b, e) {
    var h = ''
		    var n = a / 8
		    var g
		    var d
		    var p
		    var f; f = b === -1 ? 3 : 0; for (g = 0; g < n; g += 3) {
      for (d = g + 1 < n ? c[g + 1 >>> 2] : 0, p = g + 2 < n ? c[g + 2 >>> 2] : 0, p = (c[g >>> 2] >>> 8 * (f + g % 4 * b) & 255) << 16 | (d >>> 8 * (f + (g + 1) % 4 * b) & 255) << 8 | p >>> 8 * (f + (g + 2) % 4 * b) & 255, d = 0; d < 4; d += 1) {
        8 * g + 6 * d <= a ? h += 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.charAt(p >>> 6 * (3 - d) & 63) : h += e.b64Pad
      }
    } return h
  } function Q(c, a, b) {
    var e = ''; a /= 8; var h, d, g; g = b === -1 ? 3 : 0; for (h = 0; h < a; h += 1) {
      d = c[h >>> 2] >>> 8 * (g + h % 4 * b) & 255, e += String.fromCharCode(d)
    } return e
  } function R(c, a, b) {
    a /= 8; var e
		    var h = new ArrayBuffer(a)
		    var d
		    var g; g = new Uint8Array(h); d = b === -1 ? 3 : 0; for (e = 0; e < a; e += 1) {
      g[e] = c[e >>> 2] >>> 8 * (d + e % 4 * b) & 255
    } return h
  } function N(c) {
    var a = { outputUpper: !1, b64Pad: '=', shakeLen: -1 }; c = c || {}
    a.outputUpper = c.outputUpper || !1; !0 === c.hasOwnProperty('b64Pad') && (a.b64Pad = c.b64Pad); if (!0 === c.hasOwnProperty('shakeLen')) {
      if (c.shakeLen % 8 !== 0) throw Error('shakeLen must be a multiple of 8'); a.shakeLen = c.shakeLen
    } if (typeof a.outputUpper !== 'boolean') throw Error('Invalid outputUpper formatting option'); if (typeof a.b64Pad !== 'string') throw Error('Invalid b64Pad formatting option'); return a
  } function M(c, a, b) {
    switch (a) {
      case 'UTF8':case 'UTF16BE':case 'UTF16LE':
        break; default:
        throw Error('encoding must be UTF8, UTF16BE, or UTF16LE')
    } switch (c) {
      case 'HEX':
        c = function c(a, _c, d) {
          var g = a.length
					    var l
					    var p
					    var f
					    var m
					    var q
					    var u; if (g % 2 !== 0) throw Error('String of HEX type must be in byte increments'); _c = _c || [0]; d = d || 0; q = d >>> 3; u = b === -1 ? 3 : 0; for (l = 0; l < g; l += 2) {
            p = parseInt(a.substr(l, 2), 16); if (isNaN(p)) throw Error('String of HEX type contains invalid characters'); m = (l >>> 1) + q; for (f = m >>> 2; _c.length <= f;) {
              _c.push(0)
            }_c[f] |= p << 8 * (u + m % 4 * b)
          } return { value: _c, binLen: 4 * g + d }
        }; break; case 'TEXT':
        c = function c(_c2, h, d) {
          var g
					    var l
					    var p = 0
					    var f
					    var m
					    var q
					    var u
					    var r
					    var t; h = h || [0]; d = d || 0; q = d >>> 3; if (a === 'UTF8') {
            for (t = b === -1 ? 3 : 0, f = 0; f < _c2.length; f += 1) {
              for (g = _c2.charCodeAt(f), l = [], g < 128 ? l.push(g) : g < 2048 ? (l.push(192 | g >>> 6), l.push(128 | g & 63)) : g < 55296 || g >= 57344 ? l.push(224 | g >>> 12, 128 | g >>> 6 & 63, 128 | g & 63) : (f += 1, g = 65536 + ((g & 1023) << 10 | _c2.charCodeAt(f) & 1023), l.push(240 | g >>> 18, 128 | g >>> 12 & 63, 128 | g >>> 6 & 63, 128 | g & 63)), m = 0; m < l.length; m += 1) {
                r = p + q; for (u = r >>> 2; h.length <= u;) {
                  h.push(0)
                }h[u] |= l[m] << 8 * (t + r % 4 * b); p += 1
              }
            }
          } else if (a === 'UTF16BE' || a === 'UTF16LE') {
            for (t = b === -1 ? 2 : 0, l = a === 'UTF16LE' && b !== 1 || a !== 'UTF16LE' && b === 1, f = 0; f < _c2.length; f += 1) {
              g = _c2.charCodeAt(f)
              !0 === l && (m = g & 255, g = m << 8 | g >>> 8); r = p + q; for (u = r >>> 2; h.length <= u;) {
                h.push(0)
              }h[u] |= g << 8 * (t + r % 4 * b); p += 2
            }
          } return { value: h, binLen: 8 * p + d }
        }; break; case 'B64':
        c = function c(a, _c3, d) {
          var g = 0
					    var l
					    var p
					    var f
					    var m
					    var q
					    var u
					    var r
					    var t; if (a.search(/^[a-zA-Z0-9=+\/]+$/) === -1) throw Error('Invalid character in base-64 string'); p = a.indexOf('='); a = a.replace(/\=/g, ''); if (p !== -1 && p < a.length) throw Error("Invalid '=' found in base-64 string"); _c3 = _c3 || [0]; d = d || 0; u = d >>> 3; t = b === -1 ? 3 : 0; for (p = 0; p < a.length; p += 4) {
            q = a.substr(p, 4); for (f = m = 0; f < q.length; f += 1) {
              l = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.indexOf(q[f]), m |= l << 18 - 6 * f
            } for (f = 0; f < q.length - 1; f += 1) {
              r = g + u; for (l = r >>> 2; _c3.length <= l;) {
                _c3.push(0)
              }_c3[l] |= (m >>> 16 - 8 * f & 255) << 8 * (t + r % 4 * b); g += 1
            }
          } return { value: _c3, binLen: 8 * g + d }
        }; break; case 'BYTES':
        c = function c(a, _c4, d) {
          var g, l, p, f, m, q; _c4 = _c4 || [0]; d = d || 0; p = d >>> 3; q = b === -1 ? 3 : 0; for (l = 0; l < a.length; l += 1) {
            g = a.charCodeAt(l), m = l + p, f = m >>> 2, _c4.length <= f && _c4.push(0), _c4[f] |= g << 8 * (q + m % 4 * b)
          } return { value: _c4, binLen: 8 * a.length + d }
        }; break; case 'ARRAYBUFFER':
        try {
          c = new ArrayBuffer(0)
        } catch (e) {
          throw Error('ARRAYBUFFER not supported by this environment')
        }c = function c(a, _c5, d) {
          var g, l, p, f, m, q; _c5 = _c5 || [0]; d = d || 0; l = d >>> 3; m = b === -1 ? 3 : 0; q = new Uint8Array(a); for (g = 0; g < a.byteLength; g += 1) {
            f = g + l, p = f >>> 2, _c5.length <= p && _c5.push(0), _c5[p] |= q[g] << 8 * (m + f % 4 * b)
          } return { value: _c5, binLen: 8 * a.byteLength + d }
        }; break; default:
        throw Error('format must be HEX, TEXT, B64, BYTES, or ARRAYBUFFER')
    } return c
  } function y(c, a) {
    return c << a | c >>> 32 - a
  } function S(c, a) {
    return a > 32 ? (a -= 32, new b(c.b << a | c.a >>> 32 - a, c.a << a | c.b >>> 32 - a)) : a !== 0 ? new b(c.a << a | c.b >>> 32 - a, c.b << a | c.a >>> 32 - a) : c
  } function w(c, a) {
    return c >>> a | c << 32 - a
  } function t(c, a) {
    var k = null
		    var k = new b(c.a, c.b); return k = a <= 32 ? new b(k.a >>> a | k.b << 32 - a & 4294967295, k.b >>> a | k.a << 32 - a & 4294967295) : new b(k.b >>> a - 32 | k.a << 64 - a & 4294967295, k.a >>> a - 32 | k.b << 64 - a & 4294967295)
  } function T(c, a) {
    var k = null; return k = a <= 32 ? new b(c.a >>> a, c.b >>> a | c.a << 32 - a & 4294967295) : new b(0, c.a >>> a - 32)
  } function aa(c, a, b) {
    return c & a ^ ~c & b
  } function ba(c, a, k) {
    return new b(c.a & a.a ^ ~c.a & k.a, c.b & a.b ^ ~c.b & k.b)
  } function U(c, a, b) {
    return c & a ^ c & b ^ a & b
  } function ca(c, a, k) {
    return new b(c.a & a.a ^ c.a & k.a ^ a.a & k.a, c.b & a.b ^ c.b & k.b ^ a.b & k.b)
  } function da(c) {
    return w(c, 2) ^ w(c, 13) ^ w(c, 22)
  } function ea(c) {
    var a = t(c, 28)
		    var k = t(c, 34); c = t(c, 39); return new b(a.a ^ k.a ^ c.a, a.b ^ k.b ^ c.b)
  } function fa(c) {
    return w(c, 6) ^ w(c, 11) ^ w(c, 25)
  } function ga(c) {
    var a = t(c, 14)
		    var k = t(c, 18); c = t(c, 41); return new b(a.a ^ k.a ^ c.a, a.b ^ k.b ^ c.b)
  } function ha(c) {
    return w(c, 7) ^ w(c, 18) ^ c >>> 3
  } function ia(c) {
    var a = t(c, 1)
		    var k = t(c, 8); c = T(c, 7); return new b(a.a ^ k.a ^ c.a, a.b ^ k.b ^ c.b)
  } function ja(c) {
    return w(c, 17) ^ w(c, 19) ^ c >>> 10
  } function ka(c) {
    var a = t(c, 19)
		    var k = t(c, 61)
    c = T(c, 6); return new b(a.a ^ k.a ^ c.a, a.b ^ k.b ^ c.b)
  } function G(c, a) {
    var b = (c & 65535) + (a & 65535); return ((c >>> 16) + (a >>> 16) + (b >>> 16) & 65535) << 16 | b & 65535
  } function la(c, a, b, e) {
    var h = (c & 65535) + (a & 65535) + (b & 65535) + (e & 65535); return ((c >>> 16) + (a >>> 16) + (b >>> 16) + (e >>> 16) + (h >>> 16) & 65535) << 16 | h & 65535
  } function H(c, a, b, e, h) {
    var d = (c & 65535) + (a & 65535) + (b & 65535) + (e & 65535) + (h & 65535); return ((c >>> 16) + (a >>> 16) + (b >>> 16) + (e >>> 16) + (h >>> 16) + (d >>> 16) & 65535) << 16 | d & 65535
  } function ma(c, a) {
    var d, e, h; d = (c.b & 65535) + (a.b & 65535); e = (c.b >>> 16) + (a.b >>> 16) + (d >>> 16); h = (e & 65535) << 16 | d & 65535; d = (c.a & 65535) + (a.a & 65535) + (e >>> 16); e = (c.a >>> 16) + (a.a >>> 16) + (d >>> 16); return new b((e & 65535) << 16 | d & 65535, h)
  } function na(c, a, d, e) {
    var h, n, g; h = (c.b & 65535) + (a.b & 65535) + (d.b & 65535) + (e.b & 65535); n = (c.b >>> 16) + (a.b >>> 16) + (d.b >>> 16) + (e.b >>> 16) + (h >>> 16); g = (n & 65535) << 16 | h & 65535; h = (c.a & 65535) + (a.a & 65535) + (d.a & 65535) + (e.a & 65535) + (n >>> 16); n = (c.a >>> 16) + (a.a >>> 16) + (d.a >>> 16) + (e.a >>> 16) + (h >>> 16); return new b((n & 65535) << 16 | h & 65535, g)
  } function oa(c, a, d, e, h) {
    var n, g, l; n = (c.b & 65535) + (a.b & 65535) + (d.b & 65535) + (e.b & 65535) + (h.b & 65535); g = (c.b >>> 16) + (a.b >>> 16) + (d.b >>> 16) + (e.b >>> 16) + (h.b >>> 16) + (n >>> 16); l = (g & 65535) << 16 | n & 65535; n = (c.a & 65535) + (a.a & 65535) + (d.a & 65535) + (e.a & 65535) + (h.a & 65535) + (g >>> 16); g = (c.a >>> 16) + (a.a >>> 16) + (d.a >>> 16) + (e.a >>> 16) + (h.a >>> 16) + (n >>> 16); return new b((g & 65535) << 16 | n & 65535, l)
  } function B(c, a) {
    return new b(c.a ^ a.a, c.b ^ a.b)
  } function A(c) {
    var a = []
		    var d; if (c === 'SHA-1') a = [1732584193, 4023233417, 2562383102, 271733878, 3285377520]; else if (c.lastIndexOf('SHA-', 0) === 0) {
      switch (a = [3238371032, 914150663, 812702999, 4144912697, 4290775857, 1750603025, 1694076839, 3204075428], d = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225], c) {
        case 'SHA-224':
          break; case 'SHA-256':
          a = d; break; case 'SHA-384':
          a = [new b(3418070365, a[0]), new b(1654270250, a[1]), new b(2438529370, a[2]), new b(355462360, a[3]), new b(1731405415, a[4]), new b(41048885895, a[5]), new b(3675008525, a[6]), new b(1203062813, a[7])]; break; case 'SHA-512':
          a = [new b(d[0], 4089235720), new b(d[1], 2227873595), new b(d[2], 4271175723), new b(d[3], 1595750129), new b(d[4], 2917565137), new b(d[5], 725511199), new b(d[6], 4215389547), new b(d[7], 327033209)]; break; default:
          throw Error('Unknown SHA variant')
      }
    } else if (c.lastIndexOf('SHA3-', 0) === 0 || c.lastIndexOf('SHAKE', 0) === 0) {
      for (c = 0; c < 5; c += 1) {
        a[c] = [new b(0, 0), new b(0, 0), new b(0, 0), new b(0, 0), new b(0, 0)]
      }
    } else throw Error('No SHA variants supported'); return a
  } function K(c, a) {
    var b = []
		    var e
		    var d
		    var n
		    var g
		    var l
		    var p
		    var f; e = a[0]; d = a[1]; n = a[2]; g = a[3]; l = a[4]; for (f = 0; f < 80; f += 1) {
      b[f] = f < 16 ? c[f] : y(b[f - 3] ^ b[f - 8] ^ b[f - 14] ^ b[f - 16], 1), p = f < 20 ? H(y(e, 5), d & n ^ ~d & g, l, 1518500249, b[f]) : f < 40 ? H(y(e, 5), d ^ n ^ g, l, 1859775393, b[f]) : f < 60 ? H(y(e, 5), U(d, n, g), l, 2400959708, b[f]) : H(y(e, 5), d ^ n ^ g, l, 3395469782, b[f]), l = g, g = n, n = y(d, 30), d = e, e = p
    }a[0] = G(e, a[0]); a[1] = G(d, a[1]); a[2] = G(n, a[2]); a[3] = G(g, a[3]); a[4] = G(l, a[4]); return a
  } function Z(c, a, b, e) {
    var d; for (d = (a + 65 >>> 9 << 4) + 15; c.length <= d;) {
      c.push(0)
    }c[a >>> 5] |= 128 << 24 - a % 32; a += b; c[d] = a & 4294967295; c[d - 1] = a / 4294967296 | 0; a = c.length; for (d = 0; d < a; d += 16) {
      e = K(c.slice(d, d + 16), e)
    } return e
  } function L(c, a, k) {
    var e
		    var h
		    var n
		    var g
		    var l
		    var p
		    var f
		    var m
		    var q
		    var u
		    var r
		    var t
		    var v
		    var w
		    var y
		    var A
		    var z
		    var x
		    var F
		    var B
		    var C
		    var D
		    var E = []
		    var J; if (k === 'SHA-224' || k === 'SHA-256') u = 64, t = 1, D = Number, v = G, w = la, y = H, A = ha, z = ja, x = da, F = fa, C = U, B = aa, J = d; else if (k === 'SHA-384' || k === 'SHA-512') u = 80, t = 2, D = b, v = ma, w = na, y = oa, A = ia, z = ka, x = ea, F = ga, C = ca, B = ba, J = V; else throw Error('Unexpected error in SHA-2 implementation'); k = a[0]; e = a[1]; h = a[2]; n = a[3]; g = a[4]; l = a[5]; p = a[6]; f = a[7]; for (r = 0; r < u; r += 1) {
      r < 16 ? (q = r * t, m = c.length <= q ? 0 : c[q], q = c.length <= q + 1 ? 0 : c[q + 1], E[r] = new D(m, q)) : E[r] = w(z(E[r - 2]), E[r - 7], A(E[r - 15]), E[r - 16]), m = y(f, F(g), B(g, l, p), J[r], E[r]), q = v(x(k), C(k, e, h)), f = p, p = l, l = g, g = v(n, m), n = h, h = e, e = k, k = v(m, q)
    }a[0] = v(k, a[0]); a[1] = v(e, a[1]); a[2] = v(h, a[2]); a[3] = v(n, a[3]); a[4] = v(g, a[4]); a[5] = v(l, a[5]); a[6] = v(p, a[6]); a[7] = v(f, a[7]); return a
  } function D(c, a) {
    var d
		    var e
		    var h
		    var n
		    var g = []
		    var l = []; if (c !== null) {
      for (e = 0; e < c.length; e += 2) {
        a[(e >>> 1) % 5][(e >>> 1) / 5 | 0] = B(a[(e >>> 1) % 5][(e >>> 1) / 5 | 0], new b(c[e + 1], c[e]))
      }
    } for (d = 0; d < 24; d += 1) {
      n = A('SHA3-'); for (e = 0; e < 5; e += 1) {
        h = a[e][0]; var p = a[e][1]
				    var f = a[e][2]
				    var m = a[e][3]
				    var q = a[e][4]; g[e] = new b(h.a ^ p.a ^ f.a ^ m.a ^ q.a, h.b ^ p.b ^ f.b ^ m.b ^ q.b)
      } for (e = 0; e < 5; e += 1) {
        l[e] = B(g[(e + 4) % 5], S(g[(e + 1) % 5], 1))
      } for (e = 0; e < 5; e += 1) {
        for (h = 0; h < 5; h += 1) {
          a[e][h] = B(a[e][h], l[e])
        }
      } for (e = 0; e < 5; e += 1) {
        for (h = 0; h < 5; h += 1) {
          n[h][(2 * e + 3 * h) % 5] = S(a[e][h], W[e][h])
        }
      } for (e = 0; e < 5; e += 1) {
        for (h = 0; h < 5; h += 1) {
          a[e][h] = B(n[e][h], new b(~n[(e + 1) % 5][h].a & n[(e + 2) % 5][h].a, ~n[(e + 1) % 5][h].b & n[(e + 2) % 5][h].b))
        }
      }a[0][0] = B(a[0][0], X[d])
    } return a
  } var d, V, W, X; d = [1116352408, 1899447441, 3049323471, 3921009573, 961987163, 1508970993, 2453635748, 2870763221, 3624381080, 310598401, 607225278, 1426881987, 1925078388, 2162078206, 2614888103, 3248222580, 3835390401, 4022224774, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, 2554220882, 2821834349, 2952996808, 3210313671, 3336571891, 3584528711, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, 2177026350, 2456956037, 2730485921, 2820302411, 3259730800, 3345764771, 3516065817, 3600352804, 4094571909, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, 2227730452, 2361852424, 2428436474, 2756734187, 3204031479, 3329325298]; V = [new b(d[0], 3609767458), new b(d[1], 602891725), new b(d[2], 3964484399), new b(d[3], 2173295548), new b(d[4], 4081628472), new b(d[5], 3053834265), new b(d[6], 2937671579), new b(d[7], 3664609560), new b(d[8], 2734883394), new b(d[9], 1164996542), new b(d[10], 1323610764), new b(d[11], 3590304994), new b(d[12], 4068182383), new b(d[13], 991336113), new b(d[14], 633803317), new b(d[15], 3479774868), new b(d[16], 2666613458), new b(d[17], 944711139), new b(d[18], 2341262773), new b(d[19], 2007800933), new b(d[20], 1495990901), new b(d[21], 1856431235), new b(d[22], 3175218132), new b(d[23], 2198950837), new b(d[24], 3999719339), new b(d[25], 766784016), new b(d[26], 2566594879), new b(d[27], 3203337956), new b(d[28], 1034457026), new b(d[29], 2466948901), new b(d[30], 3758326383), new b(d[31], 168717936), new b(d[32], 1188179964), new b(d[33], 1546045734), new b(d[34], 1522805485), new b(d[35], 2643833823), new b(d[36], 2343527390), new b(d[37], 1014477480), new b(d[38], 1206759142), new b(d[39], 344077627), new b(d[40], 1290863460), new b(d[41], 3158454273), new b(d[42], 3505952657), new b(d[43], 106217008), new b(d[44], 3606008344), new b(d[45], 1432725776), new b(d[46], 1467031594), new b(d[47], 851169720), new b(d[48], 3100823752), new b(d[49], 1363258195), new b(d[50], 3750685593), new b(d[51], 3785050280), new b(d[52], 3318307427), new b(d[53], 3812723403), new b(d[54], 2003034995), new b(d[55], 3602036899), new b(d[56], 1575990012), new b(d[57], 1125592928), new b(d[58], 2716904306), new b(d[59], 442776044), new b(d[60], 593698344), new b(d[61], 3733110249), new b(d[62], 2999351573), new b(d[63], 3815920427), new b(3391569614, 3928383900), new b(3515267271, 566280711), new b(3940187606, 3454069534), new b(4118630271, 4000239992), new b(116418474, 1914138554), new b(174292421, 2731055270), new b(289380356, 3203993006), new b(460393269, 320620315), new b(685471733, 587496836), new b(852142971, 1086792851), new b(1017036298, 365543100), new b(1126000580, 2618297676), new b(1288033470, 3409855158), new b(1501505948, 4234509866), new b(1607167915, 987167468), new b(1816402316, 1246189591)]; X = [new b(0, 1), new b(0, 32898), new b(2147483648, 32906), new b(2147483648, 2147516416), new b(0, 32907), new b(0, 2147483649), new b(2147483648, 2147516545), new b(2147483648, 32777), new b(0, 138), new b(0, 136), new b(0, 2147516425), new b(0, 2147483658), new b(0, 2147516555), new b(2147483648, 139), new b(2147483648, 32905), new b(2147483648, 32771), new b(2147483648, 32770), new b(2147483648, 128), new b(0, 32778), new b(2147483648, 2147483658), new b(2147483648, 2147516545), new b(2147483648, 32896), new b(0, 2147483649), new b(2147483648, 2147516424)]; W = [[0, 36, 3, 41, 18], [1, 44, 10, 45, 2], [62, 6, 43, 15, 61], [28, 55, 25, 21, 56], [27, 20, 39, 8, 14]]; typeof define === 'function' && define.amd ? define('jsSHA', [], function() {
    return C
  }) : Y.jsSHA = C
})(undefined || window);

/*!
 * URI.js - Mutating URLs
 *
 * Version: 1.19.1
 *
 * Author: Rodney Rehm
 * Web: http://medialize.github.io/URI.js/
 *
 * Licensed under
 *   MIT License http://www.opensource.org/licenses/mit-license
 *
 */
(function(root, factory) {
  'use strict'

  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define('URI', [], factory)
  } else {
    // Browser globals (root is window)
    root.URI = factory(root.punycode, root.IPv6, root.SecondLevelDomains, root)
  }
})(undefined || window, function(punycode, IPv6, SLD, root) {
  'use strict'
  /*global location, escape, unescape */
  // FIXME: v2.0.0 renamce non-camelCase properties to uppercase
  /* jshint camelcase: false */

  // save current URI variable, if any

  var _URI = root && root.URI

  function URI(url, base) {
    var _urlSupplied = arguments.length >= 1
    var _baseSupplied = arguments.length >= 2

    // Allow instantiation without the 'new' keyword
    if (!(this instanceof URI)) {
      if (_urlSupplied) {
        if (_baseSupplied) {
          return new URI(url, base)
        }

        return new URI(url)
      }

      return new URI()
    }

    if (url === undefined) {
      if (_urlSupplied) {
        throw new TypeError('undefined is not a valid argument for URI')
      }

      if (typeof location !== 'undefined') {
        url = location.href + ''
      } else {
        url = ''
      }
    }

    if (url === null) {
      if (_urlSupplied) {
        throw new TypeError('null is not a valid argument for URI')
      }
    }

    this.href(url)

    // resolve to base according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#constructor
    if (base !== undefined) {
      return this.absoluteTo(base)
    }

    return this
  }

  function isInteger(value) {
    return (/^[0-9]+$/.test(value)
    )
  }

  URI.version = '1.19.1'

  var p = URI.prototype
  var hasOwn = Object.prototype.hasOwnProperty

  function escapeRegEx(string) {
    // https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963
    return string.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1')
  }

  function getType(value) {
    // IE8 doesn't return [Object Undefined] but [Object Object] for undefined value
    if (value === undefined) {
      return 'Undefined'
    }

    return String(Object.prototype.toString.call(value)).slice(8, -1)
  }

  function isArray(obj) {
    return getType(obj) === 'Array'
  }

  function filterArrayValues(data, value) {
    var lookup = {}
    var i, length

    if (getType(value) === 'RegExp') {
      lookup = null
    } else if (isArray(value)) {
      for (i = 0, length = value.length; i < length; i++) {
        lookup[value[i]] = true
      }
    } else {
      lookup[value] = true
    }

    for (i = 0, length = data.length; i < length; i++) {
      /* jshint laxbreak: true */
      var _match = lookup && lookup[data[i]] !== undefined || !lookup && value.test(data[i])
      /* jshint laxbreak: false */
      if (_match) {
        data.splice(i, 1)
        length--
        i--
      }
    }

    return data
  }

  function arrayContains(list, value) {
    var i, length

    // value may be string, number, array, regexp
    if (isArray(value)) {
      // Note: this can be optimized to O(n) (instead of current O(m * n))
      for (i = 0, length = value.length; i < length; i++) {
        if (!arrayContains(list, value[i])) {
          return false
        }
      }

      return true
    }

    var _type = getType(value)
    for (i = 0, length = list.length; i < length; i++) {
      if (_type === 'RegExp') {
        if (typeof list[i] === 'string' && list[i].match(value)) {
          return true
        }
      } else if (list[i] === value) {
        return true
      }
    }

    return false
  }

  function arraysEqual(one, two) {
    if (!isArray(one) || !isArray(two)) {
      return false
    }

    // arrays can't be equal if they have different amount of content
    if (one.length !== two.length) {
      return false
    }

    one.sort()
    two.sort()

    for (var i = 0, l = one.length; i < l; i++) {
      if (one[i] !== two[i]) {
        return false
      }
    }

    return true
  }

  function trimSlashes(text) {
    var trim_expression = /^\/+|\/+$/g
    return text.replace(trim_expression, '')
  }

  URI._parts = function() {
    return {
      protocol: null,
      username: null,
      password: null,
      hostname: null,
      urn: null,
      port: null,
      path: null,
      query: null,
      fragment: null,
      // state
      preventInvalidHostname: URI.preventInvalidHostname,
      duplicateQueryParameters: URI.duplicateQueryParameters,
      escapeQuerySpace: URI.escapeQuerySpace
    }
  }
  // state: throw on invalid hostname
  // see https://github.com/medialize/URI.js/pull/345
  // and https://github.com/medialize/URI.js/issues/354
  URI.preventInvalidHostname = false
  // state: allow duplicate query parameters (a=1&a=1)
  URI.duplicateQueryParameters = false
  // state: replaces + with %20 (space in query strings)
  URI.escapeQuerySpace = true
  // static properties
  URI.protocol_expression = /^[a-z][a-z0-9.+-]*$/i
  URI.idn_expression = /[^a-z0-9\._-]/i
  URI.punycode_expression = /(xn--)/i
  // well, 333.444.555.666 matches, but it sure ain't no IPv4 - do we care?
  URI.ip4_expression = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
  // credits to Rich Brown
  // source: http://forums.intermapper.com/viewtopic.php?p=1096#1096
  // specification: http://www.ietf.org/rfc/rfc4291.txt
  URI.ip6_expression = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/
  // expression used is "gruber revised" (@gruber v2) determined to be the
  // best solution in a regex-golf we did a couple of ages ago at
  // * http://mathiasbynens.be/demo/url-regex
  // * http://rodneyrehm.de/t/url-regex.html
  URI.find_uri_expression = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/ig
  URI.findUri = {
    // valid "scheme://" or "www."
    start: /\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi,
    // everything up to the next whitespace
    end: /[\s\r\n]|$/,
    // trim trailing punctuation captured by end RegExp
    trim: /[`!()\[\]{};:'".,<>?«»“”„‘’]+$/,
    // balanced parens inclusion (), [], {}, <>
    parens: /(\([^\)]*\)|\[[^\]]*\]|\{[^}]*\}|<[^>]*>)/g
  }
  // http://www.iana.org/assignments/uri-schemes.html
  // http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports
  URI.defaultPorts = {
    http: '80',
    https: '443',
    ftp: '21',
    gopher: '70',
    ws: '80',
    wss: '443'
  }
  // list of protocols which always require a hostname
  URI.hostProtocols = ['http', 'https']

  // allowed hostname characters according to RFC 3986
  // ALPHA DIGIT "-" "." "_" "~" "!" "$" "&" "'" "(" ")" "*" "+" "," ";" "=" %encoded
  // I've never seen a (non-IDN) hostname other than: ALPHA DIGIT . - _
  URI.invalid_hostname_characters = /[^a-zA-Z0-9\.\-:_]/
  // map DOM Elements to their URI attribute
  URI.domAttributes = {
    'a': 'href',
    'blockquote': 'cite',
    'link': 'href',
    'base': 'href',
    'script': 'src',
    'form': 'action',
    'img': 'src',
    'area': 'href',
    'iframe': 'src',
    'embed': 'src',
    'source': 'src',
    'track': 'src',
    'input': 'src', // but only if type="image"
    'audio': 'src',
    'video': 'src'
  }
  URI.getDomAttribute = function(node) {
    if (!node || !node.nodeName) {
      return undefined
    }

    var nodeName = node.nodeName.toLowerCase()
    // <input> should only expose src for type="image"
    if (nodeName === 'input' && node.type !== 'image') {
      return undefined
    }

    return URI.domAttributes[nodeName]
  }

  function escapeForDumbFirefox36(value) {
    // https://github.com/medialize/URI.js/issues/91
    return escape(value)
  }

  // encoding / decoding according to RFC3986
  function strictEncodeURIComponent(string) {
    // see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent
    return encodeURIComponent(string).replace(/[!'()*]/g, escapeForDumbFirefox36).replace(/\*/g, '%2A')
  }
  URI.encode = strictEncodeURIComponent
  URI.decode = decodeURIComponent
  URI.iso8859 = function() {
    URI.encode = escape
    URI.decode = unescape
  }
  URI.unicode = function() {
    URI.encode = strictEncodeURIComponent
    URI.decode = decodeURIComponent
  }
  URI.characters = {
    pathname: {
      encode: {
        // RFC3986 2.1: For consistency, URI producers and normalizers should
        // use uppercase hexadecimal digits for all percent-encodings.
        expression: /%(24|26|2B|2C|3B|3D|3A|40)/ig,
        map: {
          // -._~!'()*
          '%24': '$',
          '%26': '&',
          '%2B': '+',
          '%2C': ',',
          '%3B': ';',
          '%3D': '=',
          '%3A': ':',
          '%40': '@'
        }
      },
      decode: {
        expression: /[\/\?#]/g,
        map: {
          '/': '%2F',
          '?': '%3F',
          '#': '%23'
        }
      }
    },
    reserved: {
      encode: {
        // RFC3986 2.1: For consistency, URI producers and normalizers should
        // use uppercase hexadecimal digits for all percent-encodings.
        expression: /%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig,
        map: {
          // gen-delims
          '%3A': ':',
          '%2F': '/',
          '%3F': '?',
          '%23': '#',
          '%5B': '[',
          '%5D': ']',
          '%40': '@',
          // sub-delims
          '%21': '!',
          '%24': '$',
          '%26': '&',
          '%27': '\'',
          '%28': '(',
          '%29': ')',
          '%2A': '*',
          '%2B': '+',
          '%2C': ',',
          '%3B': ';',
          '%3D': '='
        }
      }
    },
    urnpath: {
      // The characters under `encode` are the characters called out by RFC 2141 as being acceptable
      // for usage in a URN. RFC2141 also calls out "-", ".", and "_" as acceptable characters, but
      // these aren't encoded by encodeURIComponent, so we don't have to call them out here. Also
      // note that the colon character is not featured in the encoding map; this is because URI.js
      // gives the colons in URNs semantic meaning as the delimiters of path segements, and so it
      // should not appear unencoded in a segment itself.
      // See also the note above about RFC3986 and capitalalized hex digits.
      encode: {
        expression: /%(21|24|27|28|29|2A|2B|2C|3B|3D|40)/ig,
        map: {
          '%21': '!',
          '%24': '$',
          '%27': '\'',
          '%28': '(',
          '%29': ')',
          '%2A': '*',
          '%2B': '+',
          '%2C': ',',
          '%3B': ';',
          '%3D': '=',
          '%40': '@'
        }
      },
      // These characters are the characters called out by RFC2141 as "reserved" characters that
      // should never appear in a URN, plus the colon character (see note above).
      decode: {
        expression: /[\/\?#:]/g,
        map: {
          '/': '%2F',
          '?': '%3F',
          '#': '%23',
          ':': '%3A'
        }
      }
    }
  }
  URI.encodeQuery = function(string, escapeQuerySpace) {
    var escaped = URI.encode(string + '')
    if (escapeQuerySpace === undefined) {
      escapeQuerySpace = URI.escapeQuerySpace
    }

    return escapeQuerySpace ? escaped.replace(/%20/g, '+') : escaped
  }
  URI.decodeQuery = function(string, escapeQuerySpace) {
    string += ''
    if (escapeQuerySpace === undefined) {
      escapeQuerySpace = URI.escapeQuerySpace
    }

    try {
      return URI.decode(escapeQuerySpace ? string.replace(/\+/g, '%20') : string)
    } catch (e) {
      // we're not going to mess with weird encodings,
      // give up and return the undecoded original string
      // see https://github.com/medialize/URI.js/issues/87
      // see https://github.com/medialize/URI.js/issues/92
      return string
    }
  }
  // generate encode/decode path functions
  var _parts = { 'encode': 'encode', 'decode': 'decode' }
  var _part
  var generateAccessor = function generateAccessor(_group, _part) {
    return function(string) {
      try {
        return URI[_part](string + '').replace(URI.characters[_group][_part].expression, function(c) {
          return URI.characters[_group][_part].map[c]
        })
      } catch (e) {
        // we're not going to mess with weird encodings,
        // give up and return the undecoded original string
        // see https://github.com/medialize/URI.js/issues/87
        // see https://github.com/medialize/URI.js/issues/92
        return string
      }
    }
  }

  for (_part in _parts) {
    URI[_part + 'PathSegment'] = generateAccessor('pathname', _parts[_part])
    URI[_part + 'UrnPathSegment'] = generateAccessor('urnpath', _parts[_part])
  }

  var generateSegmentedPathFunction = function generateSegmentedPathFunction(_sep, _codingFuncName, _innerCodingFuncName) {
    return function(string) {
      // Why pass in names of functions, rather than the function objects themselves? The
      // definitions of some functions (but in particular, URI.decode) will occasionally change due
      // to URI.js having ISO8859 and Unicode modes. Passing in the name and getting it will ensure
      // that the functions we use here are "fresh".
      var actualCodingFunc
      if (!_innerCodingFuncName) {
        actualCodingFunc = URI[_codingFuncName]
      } else {
        actualCodingFunc = function actualCodingFunc(string) {
          return URI[_codingFuncName](URI[_innerCodingFuncName](string))
        }
      }

      var segments = (string + '').split(_sep)

      for (var i = 0, length = segments.length; i < length; i++) {
        segments[i] = actualCodingFunc(segments[i])
      }

      return segments.join(_sep)
    }
  }

  // This takes place outside the above loop because we don't want, e.g., encodeUrnPath functions.
  URI.decodePath = generateSegmentedPathFunction('/', 'decodePathSegment')
  URI.decodeUrnPath = generateSegmentedPathFunction(':', 'decodeUrnPathSegment')
  URI.recodePath = generateSegmentedPathFunction('/', 'encodePathSegment', 'decode')
  URI.recodeUrnPath = generateSegmentedPathFunction(':', 'encodeUrnPathSegment', 'decode')

  URI.encodeReserved = generateAccessor('reserved', 'encode')

  URI.parse = function(string, parts) {
    var pos
    if (!parts) {
      parts = {
        preventInvalidHostname: URI.preventInvalidHostname
      }
    }
    // [protocol"://"[username[":"password]"@"]hostname[":"port]"/"?][path]["?"querystring]["#"fragment]

    // extract fragment
    pos = string.indexOf('#')
    if (pos > -1) {
      // escaping?
      parts.fragment = string.substring(pos + 1) || null
      string = string.substring(0, pos)
    }

    // extract query
    pos = string.indexOf('?')
    if (pos > -1) {
      // escaping?
      parts.query = string.substring(pos + 1) || null
      string = string.substring(0, pos)
    }

    // extract protocol
    if (string.substring(0, 2) === '//') {
      // relative-scheme
      parts.protocol = null
      string = string.substring(2)
      // extract "user:pass@host:port"
      string = URI.parseAuthority(string, parts)
    } else {
      pos = string.indexOf(':')
      if (pos > -1) {
        parts.protocol = string.substring(0, pos) || null
        if (parts.protocol && !parts.protocol.match(URI.protocol_expression)) {
          // : may be within the path
          parts.protocol = undefined
        } else if (string.substring(pos + 1, pos + 3) === '//') {
          string = string.substring(pos + 3)

          // extract "user:pass@host:port"
          string = URI.parseAuthority(string, parts)
        } else {
          string = string.substring(pos + 1)
          parts.urn = true
        }
      }
    }

    // what's left must be the path
    parts.path = string

    // and we're done
    return parts
  }
  URI.parseHost = function(string, parts) {
    if (!string) {
      string = ''
    }

    // Copy chrome, IE, opera backslash-handling behavior.
    // Back slashes before the query string get converted to forward slashes
    // See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124
    // See: https://code.google.com/p/chromium/issues/detail?id=25916
    // https://github.com/medialize/URI.js/pull/233
    string = string.replace(/\\/g, '/')

    // extract host:port
    var pos = string.indexOf('/')
    var bracketPos
    var t

    if (pos === -1) {
      pos = string.length
    }

    if (string.charAt(0) === '[') {
      // IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6
      // I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts
      // IPv6+port in the format [2001:db8::1]:80 (for the time being)
      bracketPos = string.indexOf(']')
      parts.hostname = string.substring(1, bracketPos) || null
      parts.port = string.substring(bracketPos + 2, pos) || null
      if (parts.port === '/') {
        parts.port = null
      }
    } else {
      var firstColon = string.indexOf(':')
      var firstSlash = string.indexOf('/')
      var nextColon = string.indexOf(':', firstColon + 1)
      if (nextColon !== -1 && (firstSlash === -1 || nextColon < firstSlash)) {
        // IPv6 host contains multiple colons - but no port
        // this notation is actually not allowed by RFC 3986, but we're a liberal parser
        parts.hostname = string.substring(0, pos) || null
        parts.port = null
      } else {
        t = string.substring(0, pos).split(':')
        parts.hostname = t[0] || null
        parts.port = t[1] || null
      }
    }

    if (parts.hostname && string.substring(pos).charAt(0) !== '/') {
      pos++
      string = '/' + string
    }

    if (parts.preventInvalidHostname) {
      URI.ensureValidHostname(parts.hostname, parts.protocol)
    }

    if (parts.port) {
      URI.ensureValidPort(parts.port)
    }

    return string.substring(pos) || '/'
  }
  URI.parseAuthority = function(string, parts) {
    string = URI.parseUserinfo(string, parts)
    return URI.parseHost(string, parts)
  }
  URI.parseUserinfo = function(string, parts) {
    // extract username:password
    var firstSlash = string.indexOf('/')
    var pos = string.lastIndexOf('@', firstSlash > -1 ? firstSlash : string.length - 1)
    var t

    // authority@ must come before /path
    if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) {
      t = string.substring(0, pos).split(':')
      parts.username = t[0] ? URI.decode(t[0]) : null
      t.shift()
      parts.password = t[0] ? URI.decode(t.join(':')) : null
      string = string.substring(pos + 1)
    } else {
      parts.username = null
      parts.password = null
    }

    return string
  }
  URI.parseQuery = function(string, escapeQuerySpace) {
    if (!string) {
      return {}
    }

    // throw out the funky business - "?"[name"="value"&"]+
    string = string.replace(/&+/g, '&').replace(/^\?*&*|&+$/g, '')

    if (!string) {
      return {}
    }

    var items = {}
    var splits = string.split('&')
    var length = splits.length
    var v, name, value

    for (var i = 0; i < length; i++) {
      v = splits[i].split('=')
      name = URI.decodeQuery(v.shift(), escapeQuerySpace)
      // no "=" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters
      value = v.length ? URI.decodeQuery(v.join('='), escapeQuerySpace) : null

      if (hasOwn.call(items, name)) {
        if (typeof items[name] === 'string' || items[name] === null) {
          items[name] = [items[name]]
        }

        items[name].push(value)
      } else {
        items[name] = value
      }
    }

    return items
  }

  URI.build = function(parts) {
    var t = ''

    if (parts.protocol) {
      t += parts.protocol + ':'
    }

    if (!parts.urn && (t || parts.hostname)) {
      t += '//'
    }

    t += URI.buildAuthority(parts) || ''

    if (typeof parts.path === 'string') {
      if (parts.path.charAt(0) !== '/' && typeof parts.hostname === 'string') {
        t += '/'
      }

      t += parts.path
    }

    if (typeof parts.query === 'string' && parts.query) {
      t += '?' + parts.query
    }

    if (typeof parts.fragment === 'string' && parts.fragment) {
      t += '#' + parts.fragment
    }
    return t
  }
  URI.buildHost = function(parts) {
    var t = ''

    if (!parts.hostname) {
      return ''
    } else if (URI.ip6_expression.test(parts.hostname)) {
      t += '[' + parts.hostname + ']'
    } else {
      t += parts.hostname
    }

    if (parts.port) {
      t += ':' + parts.port
    }

    return t
  }
  URI.buildAuthority = function(parts) {
    return URI.buildUserinfo(parts) + URI.buildHost(parts)
  }
  URI.buildUserinfo = function(parts) {
    var t = ''

    if (parts.username) {
      t += URI.encode(parts.username)
    }

    if (parts.password) {
      t += ':' + URI.encode(parts.password)
    }

    if (t) {
      t += '@'
    }

    return t
  }
  URI.buildQuery = function(data, duplicateQueryParameters, escapeQuerySpace) {
    // according to http://tools.ietf.org/html/rfc3986 or http://labs.apache.org/webarch/uri/rfc/rfc3986.html
    // being »-._~!$&'()*+,;=:@/?« %HEX and alnum are allowed
    // the RFC explicitly states ?/foo being a valid use case, no mention of parameter syntax!
    // URI.js treats the query string as being application/x-www-form-urlencoded
    // see http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type

    var t = ''
    var unique, key, i, length
    for (key in data) {
      if (hasOwn.call(data, key) && key) {
        if (isArray(data[key])) {
          unique = {}
          for (i = 0, length = data[key].length; i < length; i++) {
            if (data[key][i] !== undefined && unique[data[key][i] + ''] === undefined) {
              t += '&' + URI.buildQueryParameter(key, data[key][i], escapeQuerySpace)
              if (duplicateQueryParameters !== true) {
                unique[data[key][i] + ''] = true
              }
            }
          }
        } else if (data[key] !== undefined) {
          t += '&' + URI.buildQueryParameter(key, data[key], escapeQuerySpace)
        }
      }
    }

    return t.substring(1)
  }
  URI.buildQueryParameter = function(name, value, escapeQuerySpace) {
    // http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type -- application/x-www-form-urlencoded
    // don't append "=" for null values, according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#url-parameter-serialization
    return URI.encodeQuery(name, escapeQuerySpace) + (value !== null ? '=' + URI.encodeQuery(value, escapeQuerySpace) : '')
  }

  URI.addQuery = function(data, name, value) {
    if ((typeof name === 'undefined' ? 'undefined' : _typeof(name)) === 'object') {
      for (var key in name) {
        if (hasOwn.call(name, key)) {
          URI.addQuery(data, key, name[key])
        }
      }
    } else if (typeof name === 'string') {
      if (data[name] === undefined) {
        data[name] = value
        return
      } else if (typeof data[name] === 'string') {
        data[name] = [data[name]]
      }

      if (!isArray(value)) {
        value = [value]
      }

      data[name] = (data[name] || []).concat(value)
    } else {
      throw new TypeError('URI.addQuery() accepts an object, string as the name parameter')
    }
  }

  URI.setQuery = function(data, name, value) {
    if ((typeof name === 'undefined' ? 'undefined' : _typeof(name)) === 'object') {
      for (var key in name) {
        if (hasOwn.call(name, key)) {
          URI.setQuery(data, key, name[key])
        }
      }
    } else if (typeof name === 'string') {
      data[name] = value === undefined ? null : value
    } else {
      throw new TypeError('URI.setQuery() accepts an object, string as the name parameter')
    }
  }

  URI.removeQuery = function(data, name, value) {
    var i, length, key

    if (isArray(name)) {
      for (i = 0, length = name.length; i < length; i++) {
        data[name[i]] = undefined
      }
    } else if (getType(name) === 'RegExp') {
      for (key in data) {
        if (name.test(key)) {
          data[key] = undefined
        }
      }
    } else if ((typeof name === 'undefined' ? 'undefined' : _typeof(name)) === 'object') {
      for (key in name) {
        if (hasOwn.call(name, key)) {
          URI.removeQuery(data, key, name[key])
        }
      }
    } else if (typeof name === 'string') {
      if (value !== undefined) {
        if (getType(value) === 'RegExp') {
          if (!isArray(data[name]) && value.test(data[name])) {
            data[name] = undefined
          } else {
            data[name] = filterArrayValues(data[name], value)
          }
        } else if (data[name] === String(value) && (!isArray(value) || value.length === 1)) {
          data[name] = undefined
        } else if (isArray(data[name])) {
          data[name] = filterArrayValues(data[name], value)
        }
      } else {
        data[name] = undefined
      }
    } else {
      throw new TypeError('URI.removeQuery() accepts an object, string, RegExp as the first parameter')
    }
  }
  URI.hasQuery = function(data, name, value, withinArray) {
    switch (getType(name)) {
      case 'String':
        // Nothing to do here
        break

      case 'RegExp':
        for (var key in data) {
          if (hasOwn.call(data, key)) {
            if (name.test(key) && (value === undefined || URI.hasQuery(data, key, value))) {
              return true
            }
          }
        }

        return false

      case 'Object':
        for (var _key in name) {
          if (hasOwn.call(name, _key)) {
            if (!URI.hasQuery(data, _key, name[_key])) {
              return false
            }
          }
        }

        return true

      default:
        throw new TypeError('URI.hasQuery() accepts a string, regular expression or object as the name parameter')
    }

    switch (getType(value)) {
      case 'Undefined':
        // true if exists (but may be empty)
        return name in data // data[name] !== undefined;

      case 'Boolean':
        // true if exists and non-empty
        var _booly = Boolean(isArray(data[name]) ? data[name].length : data[name])
        return value === _booly

      case 'Function':
        // allow complex comparison
        return !!value(data[name], name, data)

      case 'Array':
        if (!isArray(data[name])) {
          return false
        }

        var op = withinArray ? arrayContains : arraysEqual
        return op(data[name], value)

      case 'RegExp':
        if (!isArray(data[name])) {
          return Boolean(data[name] && data[name].match(value))
        }

        if (!withinArray) {
          return false
        }

        return arrayContains(data[name], value)

      case 'Number':
        value = String(value)
        /* falls through */
      case 'String':
        if (!isArray(data[name])) {
          return data[name] === value
        }

        if (!withinArray) {
          return false
        }

        return arrayContains(data[name], value)

      default:
        throw new TypeError('URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter')
    }
  }

  URI.joinPaths = function() {
    var input = []
    var segments = []
    var nonEmptySegments = 0

    for (var i = 0; i < arguments.length; i++) {
      var url = new URI(arguments[i])
      input.push(url)
      var _segments = url.segment()
      for (var s = 0; s < _segments.length; s++) {
        if (typeof _segments[s] === 'string') {
          segments.push(_segments[s])
        }

        if (_segments[s]) {
          nonEmptySegments++
        }
      }
    }

    if (!segments.length || !nonEmptySegments) {
      return new URI('')
    }

    var uri = new URI('').segment(segments)

    if (input[0].path() === '' || input[0].path().slice(0, 1) === '/') {
      uri.path('/' + uri.path())
    }

    return uri.normalize()
  }

  URI.commonPath = function(one, two) {
    var length = Math.min(one.length, two.length)
    var pos

    // find first non-matching character
    for (pos = 0; pos < length; pos++) {
      if (one.charAt(pos) !== two.charAt(pos)) {
        pos--
        break
      }
    }

    if (pos < 1) {
      return one.charAt(0) === two.charAt(0) && one.charAt(0) === '/' ? '/' : ''
    }

    // revert to last /
    if (one.charAt(pos) !== '/' || two.charAt(pos) !== '/') {
      pos = one.substring(0, pos).lastIndexOf('/')
    }

    return one.substring(0, pos + 1)
  }

  URI.withinString = function(string, callback, options) {
    options || (options = {})
    var _start = options.start || URI.findUri.start
    var _end = options.end || URI.findUri.end
    var _trim = options.trim || URI.findUri.trim
    var _parens = options.parens || URI.findUri.parens
    var _attributeOpen = /[a-z0-9-]=["']?$/i

    _start.lastIndex = 0
    while (true) {
      var match = _start.exec(string)
      if (!match) {
        break
      }

      var start = match.index
      if (options.ignoreHtml) {
        // attribut(e=["']?$)
        var attributeOpen = string.slice(Math.max(start - 3, 0), start)
        if (attributeOpen && _attributeOpen.test(attributeOpen)) {
          continue
        }
      }

      var end = start + string.slice(start).search(_end)
      var slice = string.slice(start, end)
      // make sure we include well balanced parens
      var parensEnd = -1
      while (true) {
        var parensMatch = _parens.exec(slice)
        if (!parensMatch) {
          break
        }

        var parensMatchEnd = parensMatch.index + parensMatch[0].length
        parensEnd = Math.max(parensEnd, parensMatchEnd)
      }

      if (parensEnd > -1) {
        slice = slice.slice(0, parensEnd) + slice.slice(parensEnd).replace(_trim, '')
      } else {
        slice = slice.replace(_trim, '')
      }

      if (slice.length <= match[0].length) {
        // the extract only contains the starting marker of a URI,
        // e.g. "www" or "http://"
        continue
      }

      if (options.ignore && options.ignore.test(slice)) {
        continue
      }

      end = start + slice.length
      var result = callback(slice, start, end, string)
      if (result === undefined) {
        _start.lastIndex = end
        continue
      }

      result = String(result)
      string = string.slice(0, start) + result + string.slice(end)
      _start.lastIndex = start + result.length
    }

    _start.lastIndex = 0
    return string
  }

  URI.ensureValidHostname = function(v, protocol) {
    // Theoretically URIs allow percent-encoding in Hostnames (according to RFC 3986)
    // they are not part of DNS and therefore ignored by URI.js

    var hasHostname = !!v // not null and not an empty string
    var hasProtocol = !!protocol
    var rejectEmptyHostname = false

    if (hasProtocol) {
      rejectEmptyHostname = arrayContains(URI.hostProtocols, protocol)
    }

    if (rejectEmptyHostname && !hasHostname) {
      throw new TypeError('Hostname cannot be empty, if protocol is ' + protocol)
    } else if (v && v.match(URI.invalid_hostname_characters)) {
      // test punycode
      if (!punycode) {
        throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-:_] and Punycode.js is not available')
      }
      if (punycode.toASCII(v).match(URI.invalid_hostname_characters)) {
        throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-:_]')
      }
    }
  }

  URI.ensureValidPort = function(v) {
    if (!v) {
      return
    }

    var port = Number(v)
    if (isInteger(port) && port > 0 && port < 65536) {
      return
    }

    throw new TypeError('Port "' + v + '" is not a valid port')
  }

  // noConflict
  URI.noConflict = function(removeAll) {
    if (removeAll) {
      var unconflicted = {
        URI: this.noConflict()
      }

      if (root.URITemplate && typeof root.URITemplate.noConflict === 'function') {
        unconflicted.URITemplate = root.URITemplate.noConflict()
      }

      if (root.IPv6 && typeof root.IPv6.noConflict === 'function') {
        unconflicted.IPv6 = root.IPv6.noConflict()
      }

      if (root.SecondLevelDomains && typeof root.SecondLevelDomains.noConflict === 'function') {
        unconflicted.SecondLevelDomains = root.SecondLevelDomains.noConflict()
      }

      return unconflicted
    } else if (root.URI === this) {
      root.URI = _URI
    }

    return this
  }

  p.build = function(deferBuild) {
    if (deferBuild === true) {
      this._deferred_build = true
    } else if (deferBuild === undefined || this._deferred_build) {
      this._string = URI.build(this._parts)
      this._deferred_build = false
    }

    return this
  }

  p.clone = function() {
    return new URI(this)
  }

  p.valueOf = p.toString = function() {
    return this.build(false)._string
  }

  function generateSimpleAccessor(_part) {
    return function(v, build) {
      if (v === undefined) {
        return this._parts[_part] || ''
      } else {
        this._parts[_part] = v || null
        this.build(!build)
        return this
      }
    }
  }

  function generatePrefixAccessor(_part, _key) {
    return function(v, build) {
      if (v === undefined) {
        return this._parts[_part] || ''
      } else {
        if (v !== null) {
          v = v + ''
          if (v.charAt(0) === _key) {
            v = v.substring(1)
          }
        }

        this._parts[_part] = v
        this.build(!build)
        return this
      }
    }
  }

  p.protocol = generateSimpleAccessor('protocol')
  p.username = generateSimpleAccessor('username')
  p.password = generateSimpleAccessor('password')
  p.hostname = generateSimpleAccessor('hostname')
  p.port = generateSimpleAccessor('port')
  p.query = generatePrefixAccessor('query', '?')
  p.fragment = generatePrefixAccessor('fragment', '#')

  p.search = function(v, build) {
    var t = this.query(v, build)
    return typeof t === 'string' && t.length ? '?' + t : t
  }
  p.hash = function(v, build) {
    var t = this.fragment(v, build)
    return typeof t === 'string' && t.length ? '#' + t : t
  }

  p.pathname = function(v, build) {
    if (v === undefined || v === true) {
      var res = this._parts.path || (this._parts.hostname ? '/' : '')
      return v ? (this._parts.urn ? URI.decodeUrnPath : URI.decodePath)(res) : res
    } else {
      if (this._parts.urn) {
        this._parts.path = v ? URI.recodeUrnPath(v) : ''
      } else {
        this._parts.path = v ? URI.recodePath(v) : '/'
      }
      this.build(!build)
      return this
    }
  }
  p.path = p.pathname
  p.href = function(href, build) {
    var key

    if (href === undefined) {
      return this.toString()
    }

    this._string = ''
    this._parts = URI._parts()

    var _URI = href instanceof URI
    var _object = (typeof href === 'undefined' ? 'undefined' : _typeof(href)) === 'object' && (href.hostname || href.path || href.pathname)
    if (href.nodeName) {
      var attribute = URI.getDomAttribute(href)
      href = href[attribute] || ''
      _object = false
    }

    // window.location is reported to be an object, but it's not the sort
    // of object we're looking for:
    // * location.protocol ends with a colon
    // * location.query != object.search
    // * location.hash != object.fragment
    // simply serializing the unknown object should do the trick
    // (for location, not for everything...)
    if (!_URI && _object && href.pathname !== undefined) {
      href = href.toString()
    }

    if (typeof href === 'string' || href instanceof String) {
      this._parts = URI.parse(String(href), this._parts)
    } else if (_URI || _object) {
      var src = _URI ? href._parts : href
      for (key in src) {
        if (key === 'query') {
          continue
        }
        if (hasOwn.call(this._parts, key)) {
          this._parts[key] = src[key]
        }
      }
      if (src.query) {
        this.query(src.query, false)
      }
    } else {
      throw new TypeError('invalid input')
    }

    this.build(!build)
    return this
  }

  // identification accessors
  p.is = function(what) {
    var ip = false
    var ip4 = false
    var ip6 = false
    var name = false
    var sld = false
    var idn = false
    var punycode = false
    var relative = !this._parts.urn

    if (this._parts.hostname) {
      relative = false
      ip4 = URI.ip4_expression.test(this._parts.hostname)
      ip6 = URI.ip6_expression.test(this._parts.hostname)
      ip = ip4 || ip6
      name = !ip
      sld = name && SLD && SLD.has(this._parts.hostname)
      idn = name && URI.idn_expression.test(this._parts.hostname)
      punycode = name && URI.punycode_expression.test(this._parts.hostname)
    }

    switch (what.toLowerCase()) {
      case 'relative':
        return relative

      case 'absolute':
        return !relative

        // hostname identification
      case 'domain':
      case 'name':
        return name

      case 'sld':
        return sld

      case 'ip':
        return ip

      case 'ip4':
      case 'ipv4':
      case 'inet4':
        return ip4

      case 'ip6':
      case 'ipv6':
      case 'inet6':
        return ip6

      case 'idn':
        return idn

      case 'url':
        return !this._parts.urn

      case 'urn':
        return !!this._parts.urn

      case 'punycode':
        return punycode
    }

    return null
  }

  // component specific input validation
  var _protocol = p.protocol
  var _port = p.port
  var _hostname = p.hostname

  p.protocol = function(v, build) {
    if (v) {
      // accept trailing ://
      v = v.replace(/:(\/\/)?$/, '')

      if (!v.match(URI.protocol_expression)) {
        throw new TypeError('Protocol "' + v + '" contains characters other than [A-Z0-9.+-] or doesn\'t start with [A-Z]')
      }
    }

    return _protocol.call(this, v, build)
  }
  p.scheme = p.protocol
  p.port = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this
    }

    if (v !== undefined) {
      if (v === 0) {
        v = null
      }

      if (v) {
        v += ''
        if (v.charAt(0) === ':') {
          v = v.substring(1)
        }

        URI.ensureValidPort(v)
      }
    }
    return _port.call(this, v, build)
  }
  p.hostname = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this
    }

    if (v !== undefined) {
      var x = { preventInvalidHostname: this._parts.preventInvalidHostname }
      var res = URI.parseHost(v, x)
      if (res !== '/') {
        throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]')
      }

      v = x.hostname
      if (this._parts.preventInvalidHostname) {
        URI.ensureValidHostname(v, this._parts.protocol)
      }
    }

    return _hostname.call(this, v, build)
  }

  // compound accessors
  p.origin = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this
    }

    if (v === undefined) {
      var protocol = this.protocol()
      var authority = this.authority()
      if (!authority) {
        return ''
      }

      return (protocol ? protocol + '://' : '') + this.authority()
    } else {
      var origin = URI(v)
      this.protocol(origin.protocol()).authority(origin.authority()).build(!build)
      return this
    }
  }
  p.host = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this
    }

    if (v === undefined) {
      return this._parts.hostname ? URI.buildHost(this._parts) : ''
    } else {
      var res = URI.parseHost(v, this._parts)
      if (res !== '/') {
        throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]')
      }

      this.build(!build)
      return this
    }
  }
  p.authority = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this
    }

    if (v === undefined) {
      return this._parts.hostname ? URI.buildAuthority(this._parts) : ''
    } else {
      var res = URI.parseAuthority(v, this._parts)
      if (res !== '/') {
        throw new TypeError('Hostname "' + v + '" contains characters other than [A-Z0-9.-]')
      }

      this.build(!build)
      return this
    }
  }
  p.userinfo = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this
    }

    if (v === undefined) {
      var t = URI.buildUserinfo(this._parts)
      return t ? t.substring(0, t.length - 1) : t
    } else {
      if (v[v.length - 1] !== '@') {
        v += '@'
      }

      URI.parseUserinfo(v, this._parts)
      this.build(!build)
      return this
    }
  }
  p.resource = function(v, build) {
    var parts

    if (v === undefined) {
      return this.path() + this.search() + this.hash()
    }

    parts = URI.parse(v)
    this._parts.path = parts.path
    this._parts.query = parts.query
    this._parts.fragment = parts.fragment
    this.build(!build)
    return this
  }

  // fraction accessors
  p.subdomain = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this
    }

    // convenience, return "www" from "www.example.org"
    if (v === undefined) {
      if (!this._parts.hostname || this.is('IP')) {
        return ''
      }

      // grab domain and add another segment
      var end = this._parts.hostname.length - this.domain().length - 1
      return this._parts.hostname.substring(0, end) || ''
    } else {
      var e = this._parts.hostname.length - this.domain().length
      var sub = this._parts.hostname.substring(0, e)
      var replace = new RegExp('^' + escapeRegEx(sub))

      if (v && v.charAt(v.length - 1) !== '.') {
        v += '.'
      }

      if (v.indexOf(':') !== -1) {
        throw new TypeError('Domains cannot contain colons')
      }

      if (v) {
        URI.ensureValidHostname(v, this._parts.protocol)
      }

      this._parts.hostname = this._parts.hostname.replace(replace, v)
      this.build(!build)
      return this
    }
  }
  p.domain = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this
    }

    if (typeof v === 'boolean') {
      build = v
      v = undefined
    }

    // convenience, return "example.org" from "www.example.org"
    if (v === undefined) {
      if (!this._parts.hostname || this.is('IP')) {
        return ''
      }

      // if hostname consists of 1 or 2 segments, it must be the domain
      var t = this._parts.hostname.match(/\./g)
      if (t && t.length < 2) {
        return this._parts.hostname
      }

      // grab tld and add another segment
      var end = this._parts.hostname.length - this.tld(build).length - 1
      end = this._parts.hostname.lastIndexOf('.', end - 1) + 1
      return this._parts.hostname.substring(end) || ''
    } else {
      if (!v) {
        throw new TypeError('cannot set domain empty')
      }

      if (v.indexOf(':') !== -1) {
        throw new TypeError('Domains cannot contain colons')
      }

      URI.ensureValidHostname(v, this._parts.protocol)

      if (!this._parts.hostname || this.is('IP')) {
        this._parts.hostname = v
      } else {
        var replace = new RegExp(escapeRegEx(this.domain()) + '$')
        this._parts.hostname = this._parts.hostname.replace(replace, v)
      }

      this.build(!build)
      return this
    }
  }
  p.tld = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this
    }

    if (typeof v === 'boolean') {
      build = v
      v = undefined
    }

    // return "org" from "www.example.org"
    if (v === undefined) {
      if (!this._parts.hostname || this.is('IP')) {
        return ''
      }

      var pos = this._parts.hostname.lastIndexOf('.')
      var tld = this._parts.hostname.substring(pos + 1)

      if (build !== true && SLD && SLD.list[tld.toLowerCase()]) {
        return SLD.get(this._parts.hostname) || tld
      }

      return tld
    } else {
      var replace

      if (!v) {
        throw new TypeError('cannot set TLD empty')
      } else if (v.match(/[^a-zA-Z0-9-]/)) {
        if (SLD && SLD.is(v)) {
          replace = new RegExp(escapeRegEx(this.tld()) + '$')
          this._parts.hostname = this._parts.hostname.replace(replace, v)
        } else {
          throw new TypeError('TLD "' + v + '" contains characters other than [A-Z0-9]')
        }
      } else if (!this._parts.hostname || this.is('IP')) {
        throw new ReferenceError('cannot set TLD on non-domain host')
      } else {
        replace = new RegExp(escapeRegEx(this.tld()) + '$')
        this._parts.hostname = this._parts.hostname.replace(replace, v)
      }

      this.build(!build)
      return this
    }
  }
  p.directory = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this
    }

    if (v === undefined || v === true) {
      if (!this._parts.path && !this._parts.hostname) {
        return ''
      }

      if (this._parts.path === '/') {
        return '/'
      }

      var end = this._parts.path.length - this.filename().length - 1
      var res = this._parts.path.substring(0, end) || (this._parts.hostname ? '/' : '')

      return v ? URI.decodePath(res) : res
    } else {
      var e = this._parts.path.length - this.filename().length
      var directory = this._parts.path.substring(0, e)
      var replace = new RegExp('^' + escapeRegEx(directory))

      // fully qualifier directories begin with a slash
      if (!this.is('relative')) {
        if (!v) {
          v = '/'
        }

        if (v.charAt(0) !== '/') {
          v = '/' + v
        }
      }

      // directories always end with a slash
      if (v && v.charAt(v.length - 1) !== '/') {
        v += '/'
      }

      v = URI.recodePath(v)
      this._parts.path = this._parts.path.replace(replace, v)
      this.build(!build)
      return this
    }
  }
  p.filename = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this
    }

    if (typeof v !== 'string') {
      if (!this._parts.path || this._parts.path === '/') {
        return ''
      }

      var pos = this._parts.path.lastIndexOf('/')
      var res = this._parts.path.substring(pos + 1)

      return v ? URI.decodePathSegment(res) : res
    } else {
      var mutatedDirectory = false

      if (v.charAt(0) === '/') {
        v = v.substring(1)
      }

      if (v.match(/\.?\//)) {
        mutatedDirectory = true
      }

      var replace = new RegExp(escapeRegEx(this.filename()) + '$')
      v = URI.recodePath(v)
      this._parts.path = this._parts.path.replace(replace, v)

      if (mutatedDirectory) {
        this.normalizePath(build)
      } else {
        this.build(!build)
      }

      return this
    }
  }
  p.suffix = function(v, build) {
    if (this._parts.urn) {
      return v === undefined ? '' : this
    }

    if (v === undefined || v === true) {
      if (!this._parts.path || this._parts.path === '/') {
        return ''
      }

      var filename = this.filename()
      var pos = filename.lastIndexOf('.')
      var s, res

      if (pos === -1) {
        return ''
      }

      // suffix may only contain alnum characters (yup, I made this up.)
      s = filename.substring(pos + 1)
      res = /^[a-z0-9%]+$/i.test(s) ? s : ''
      return v ? URI.decodePathSegment(res) : res
    } else {
      if (v.charAt(0) === '.') {
        v = v.substring(1)
      }

      var suffix = this.suffix()
      var replace

      if (!suffix) {
        if (!v) {
          return this
        }

        this._parts.path += '.' + URI.recodePath(v)
      } else if (!v) {
        replace = new RegExp(escapeRegEx('.' + suffix) + '$')
      } else {
        replace = new RegExp(escapeRegEx(suffix) + '$')
      }

      if (replace) {
        v = URI.recodePath(v)
        this._parts.path = this._parts.path.replace(replace, v)
      }

      this.build(!build)
      return this
    }
  }
  p.segment = function(segment, v, build) {
    var separator = this._parts.urn ? ':' : '/'
    var path = this.path()
    var absolute = path.substring(0, 1) === '/'
    var segments = path.split(separator)

    if (segment !== undefined && typeof segment !== 'number') {
      build = v
      v = segment
      segment = undefined
    }

    if (segment !== undefined && typeof segment !== 'number') {
      throw new Error('Bad segment "' + segment + '", must be 0-based integer')
    }

    if (absolute) {
      segments.shift()
    }

    if (segment < 0) {
      // allow negative indexes to address from the end
      segment = Math.max(segments.length + segment, 0)
    }

    if (v === undefined) {
      /* jshint laxbreak: true */
      return segment === undefined ? segments : segments[segment]
      /* jshint laxbreak: false */
    } else if (segment === null || segments[segment] === undefined) {
      if (isArray(v)) {
        segments = []
        // collapse empty elements within array
        for (var i = 0, l = v.length; i < l; i++) {
          if (!v[i].length && (!segments.length || !segments[segments.length - 1].length)) {
            continue
          }

          if (segments.length && !segments[segments.length - 1].length) {
            segments.pop()
          }

          segments.push(trimSlashes(v[i]))
        }
      } else if (v || typeof v === 'string') {
        v = trimSlashes(v)
        if (segments[segments.length - 1] === '') {
          // empty trailing elements have to be overwritten
          // to prevent results such as /foo//bar
          segments[segments.length - 1] = v
        } else {
          segments.push(v)
        }
      }
    } else {
      if (v) {
        segments[segment] = trimSlashes(v)
      } else {
        segments.splice(segment, 1)
      }
    }

    if (absolute) {
      segments.unshift('')
    }

    return this.path(segments.join(separator), build)
  }
  p.segmentCoded = function(segment, v, build) {
    var segments, i, l

    if (typeof segment !== 'number') {
      build = v
      v = segment
      segment = undefined
    }

    if (v === undefined) {
      segments = this.segment(segment, v, build)
      if (!isArray(segments)) {
        segments = segments !== undefined ? URI.decode(segments) : undefined
      } else {
        for (i = 0, l = segments.length; i < l; i++) {
          segments[i] = URI.decode(segments[i])
        }
      }

      return segments
    }

    if (!isArray(v)) {
      v = typeof v === 'string' || v instanceof String ? URI.encode(v) : v
    } else {
      for (i = 0, l = v.length; i < l; i++) {
        v[i] = URI.encode(v[i])
      }
    }

    return this.segment(segment, v, build)
  }

  // mutating query string
  var q = p.query
  p.query = function(v, build) {
    if (v === true) {
      return URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace)
    } else if (typeof v === 'function') {
      var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace)
      var result = v.call(this, data)
      this._parts.query = URI.buildQuery(result || data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace)
      this.build(!build)
      return this
    } else if (v !== undefined && typeof v !== 'string') {
      this._parts.query = URI.buildQuery(v, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace)
      this.build(!build)
      return this
    } else {
      return q.call(this, v, build)
    }
  }
  p.setQuery = function(name, value, build) {
    var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace)

    if (typeof name === 'string' || name instanceof String) {
      data[name] = value !== undefined ? value : null
    } else if ((typeof name === 'undefined' ? 'undefined' : _typeof(name)) === 'object') {
      for (var key in name) {
        if (hasOwn.call(name, key)) {
          data[key] = name[key]
        }
      }
    } else {
      throw new TypeError('URI.addQuery() accepts an object, string as the name parameter')
    }

    this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace)
    if (typeof name !== 'string') {
      build = value
    }

    this.build(!build)
    return this
  }
  p.addQuery = function(name, value, build) {
    var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace)
    URI.addQuery(data, name, value === undefined ? null : value)
    this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace)
    if (typeof name !== 'string') {
      build = value
    }

    this.build(!build)
    return this
  }
  p.removeQuery = function(name, value, build) {
    var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace)
    URI.removeQuery(data, name, value)
    this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters, this._parts.escapeQuerySpace)
    if (typeof name !== 'string') {
      build = value
    }

    this.build(!build)
    return this
  }
  p.hasQuery = function(name, value, withinArray) {
    var data = URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace)
    return URI.hasQuery(data, name, value, withinArray)
  }
  p.setSearch = p.setQuery
  p.addSearch = p.addQuery
  p.removeSearch = p.removeQuery
  p.hasSearch = p.hasQuery

  // sanitizing URLs
  p.normalize = function() {
    if (this._parts.urn) {
      return this.normalizeProtocol(false).normalizePath(false).normalizeQuery(false).normalizeFragment(false).build()
    }

    return this.normalizeProtocol(false).normalizeHostname(false).normalizePort(false).normalizePath(false).normalizeQuery(false).normalizeFragment(false).build()
  }
  p.normalizeProtocol = function(build) {
    if (typeof this._parts.protocol === 'string') {
      this._parts.protocol = this._parts.protocol.toLowerCase()
      this.build(!build)
    }

    return this
  }
  p.normalizeHostname = function(build) {
    if (this._parts.hostname) {
      if (this.is('IDN') && punycode) {
        this._parts.hostname = punycode.toASCII(this._parts.hostname)
      } else if (this.is('IPv6') && IPv6) {
        this._parts.hostname = IPv6.best(this._parts.hostname)
      }

      this._parts.hostname = this._parts.hostname.toLowerCase()
      this.build(!build)
    }

    return this
  }
  p.normalizePort = function(build) {
    // remove port of it's the protocol's default
    if (typeof this._parts.protocol === 'string' && this._parts.port === URI.defaultPorts[this._parts.protocol]) {
      this._parts.port = null
      this.build(!build)
    }

    return this
  }
  p.normalizePath = function(build) {
    var _path = this._parts.path
    if (!_path) {
      return this
    }

    if (this._parts.urn) {
      this._parts.path = URI.recodeUrnPath(this._parts.path)
      this.build(!build)
      return this
    }

    if (this._parts.path === '/') {
      return this
    }

    _path = URI.recodePath(_path)

    var _was_relative
    var _leadingParents = ''
    var _parent, _pos

    // handle relative paths
    if (_path.charAt(0) !== '/') {
      _was_relative = true
      _path = '/' + _path
    }

    // handle relative files (as opposed to directories)
    if (_path.slice(-3) === '/..' || _path.slice(-2) === '/.') {
      _path += '/'
    }

    // resolve simples
    _path = _path.replace(/(\/(\.\/)+)|(\/\.$)/g, '/').replace(/\/{2,}/g, '/')

    // remember leading parents
    if (_was_relative) {
      _leadingParents = _path.substring(1).match(/^(\.\.\/)+/) || ''
      if (_leadingParents) {
        _leadingParents = _leadingParents[0]
      }
    }

    // resolve parents
    while (true) {
      _parent = _path.search(/\/\.\.(\/|$)/)
      if (_parent === -1) {
        // no more ../ to resolve
        break
      } else if (_parent === 0) {
        // top level cannot be relative, skip it
        _path = _path.substring(3)
        continue
      }

      _pos = _path.substring(0, _parent).lastIndexOf('/')
      if (_pos === -1) {
        _pos = _parent
      }
      _path = _path.substring(0, _pos) + _path.substring(_parent + 3)
    }

    // revert to relative
    if (_was_relative && this.is('relative')) {
      _path = _leadingParents + _path.substring(1)
    }

    this._parts.path = _path
    this.build(!build)
    return this
  }
  p.normalizePathname = p.normalizePath
  p.normalizeQuery = function(build) {
    if (typeof this._parts.query === 'string') {
      if (!this._parts.query.length) {
        this._parts.query = null
      } else {
        this.query(URI.parseQuery(this._parts.query, this._parts.escapeQuerySpace))
      }

      this.build(!build)
    }

    return this
  }
  p.normalizeFragment = function(build) {
    if (!this._parts.fragment) {
      this._parts.fragment = null
      this.build(!build)
    }

    return this
  }
  p.normalizeSearch = p.normalizeQuery
  p.normalizeHash = p.normalizeFragment

  p.iso8859 = function() {
    // expect unicode input, iso8859 output
    var e = URI.encode
    var d = URI.decode

    URI.encode = escape
    URI.decode = decodeURIComponent
    try {
      this.normalize()
    } finally {
      URI.encode = e
      URI.decode = d
    }
    return this
  }

  p.unicode = function() {
    // expect iso8859 input, unicode output
    var e = URI.encode
    var d = URI.decode

    URI.encode = strictEncodeURIComponent
    URI.decode = unescape
    try {
      this.normalize()
    } finally {
      URI.encode = e
      URI.decode = d
    }
    return this
  }

  p.readable = function() {
    var uri = this.clone()
    // removing username, password, because they shouldn't be displayed according to RFC 3986
    uri.username('').password('').normalize()
    var t = ''
    if (uri._parts.protocol) {
      t += uri._parts.protocol + '://'
    }

    if (uri._parts.hostname) {
      if (uri.is('punycode') && punycode) {
        t += punycode.toUnicode(uri._parts.hostname)
        if (uri._parts.port) {
          t += ':' + uri._parts.port
        }
      } else {
        t += uri.host()
      }
    }

    if (uri._parts.hostname && uri._parts.path && uri._parts.path.charAt(0) !== '/') {
      t += '/'
    }

    t += uri.path(true)
    if (uri._parts.query) {
      var q = ''
      for (var i = 0, qp = uri._parts.query.split('&'), l = qp.length; i < l; i++) {
        var kv = (qp[i] || '').split('=')
        q += '&' + URI.decodeQuery(kv[0], this._parts.escapeQuerySpace).replace(/&/g, '%26')

        if (kv[1] !== undefined) {
          q += '=' + URI.decodeQuery(kv[1], this._parts.escapeQuerySpace).replace(/&/g, '%26')
        }
      }
      t += '?' + q.substring(1)
    }

    t += URI.decodeQuery(uri.hash(), true)
    return t
  }

  // resolving relative and absolute URLs
  p.absoluteTo = function(base) {
    var resolved = this.clone()
    var properties = ['protocol', 'username', 'password', 'hostname', 'port']
    var basedir, i, p

    if (this._parts.urn) {
      throw new Error('URNs do not have any generally defined hierarchical components')
    }

    if (!(base instanceof URI)) {
      base = new URI(base)
    }

    if (resolved._parts.protocol) {
      // Directly returns even if this._parts.hostname is empty.
      return resolved
    } else {
      resolved._parts.protocol = base._parts.protocol
    }

    if (this._parts.hostname) {
      return resolved
    }

    for (i = 0; p = properties[i]; i++) {
      resolved._parts[p] = base._parts[p]
    }

    if (!resolved._parts.path) {
      resolved._parts.path = base._parts.path
      if (!resolved._parts.query) {
        resolved._parts.query = base._parts.query
      }
    } else {
      if (resolved._parts.path.substring(-2) === '..') {
        resolved._parts.path += '/'
      }

      if (resolved.path().charAt(0) !== '/') {
        basedir = base.directory()
        basedir = basedir || (base.path().indexOf('/') === 0 ? '/' : '')
        resolved._parts.path = (basedir ? basedir + '/' : '') + resolved._parts.path
        resolved.normalizePath()
      }
    }

    resolved.build()
    return resolved
  }
  p.relativeTo = function(base) {
    var relative = this.clone().normalize()
    var relativeParts, baseParts, common, relativePath, basePath

    if (relative._parts.urn) {
      throw new Error('URNs do not have any generally defined hierarchical components')
    }

    base = new URI(base).normalize()
    relativeParts = relative._parts
    baseParts = base._parts
    relativePath = relative.path()
    basePath = base.path()

    if (relativePath.charAt(0) !== '/') {
      throw new Error('URI is already relative')
    }

    if (basePath.charAt(0) !== '/') {
      throw new Error('Cannot calculate a URI relative to another relative URI')
    }

    if (relativeParts.protocol === baseParts.protocol) {
      relativeParts.protocol = null
    }

    if (relativeParts.username !== baseParts.username || relativeParts.password !== baseParts.password) {
      return relative.build()
    }

    if (relativeParts.protocol !== null || relativeParts.username !== null || relativeParts.password !== null) {
      return relative.build()
    }

    if (relativeParts.hostname === baseParts.hostname && relativeParts.port === baseParts.port) {
      relativeParts.hostname = null
      relativeParts.port = null
    } else {
      return relative.build()
    }

    if (relativePath === basePath) {
      relativeParts.path = ''
      return relative.build()
    }

    // determine common sub path
    common = URI.commonPath(relativePath, basePath)

    // If the paths have nothing in common, return a relative URL with the absolute path.
    if (!common) {
      return relative.build()
    }

    var parents = baseParts.path.substring(common.length).replace(/[^\/]*$/, '').replace(/.*?\//g, '../')

    relativeParts.path = parents + relativeParts.path.substring(common.length) || './'

    return relative.build()
  }

  // comparing URIs
  p.equals = function(uri) {
    var one = this.clone()
    var two = new URI(uri)
    var one_map = {}
    var two_map = {}
    var checked = {}
    var one_query, two_query, key

    one.normalize()
    two.normalize()

    // exact match
    if (one.toString() === two.toString()) {
      return true
    }

    // extract query string
    one_query = one.query()
    two_query = two.query()
    one.query('')
    two.query('')

    // definitely not equal if not even non-query parts match
    if (one.toString() !== two.toString()) {
      return false
    }

    // query parameters have the same length, even if they're permuted
    if (one_query.length !== two_query.length) {
      return false
    }

    one_map = URI.parseQuery(one_query, this._parts.escapeQuerySpace)
    two_map = URI.parseQuery(two_query, this._parts.escapeQuerySpace)

    for (key in one_map) {
      if (hasOwn.call(one_map, key)) {
        if (!isArray(one_map[key])) {
          if (one_map[key] !== two_map[key]) {
            return false
          }
        } else if (!arraysEqual(one_map[key], two_map[key])) {
          return false
        }

        checked[key] = true
      }
    }

    for (key in two_map) {
      if (hasOwn.call(two_map, key)) {
        if (!checked[key]) {
          // two contains a parameter not present in one
          return false
        }
      }
    }

    return true
  }

  // state
  p.preventInvalidHostname = function(v) {
    this._parts.preventInvalidHostname = !!v
    return this
  }

  p.duplicateQueryParameters = function(v) {
    this._parts.duplicateQueryParameters = !!v
    return this
  }

  p.escapeQuerySpace = function(v) {
    this._parts.escapeQuerySpace = !!v
    return this
  }

  return URI
});

/*
 * JavaScript MD5
 * https://github.com/blueimp/JavaScript-MD5
 *
 * Copyright 2011, Sebastian Tschan
 * https://blueimp.net
 *
 * Licensed under the MIT license:
 * https://opensource.org/licenses/MIT
 *
 * Based on
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for more info.
 */

(function(root, factory) {
  'use strict'

  if (typeof define === 'function' && define.amd) {
    define('md5', [], factory)
  } else {
    root['md5'] = factory()
  }
})(undefined || window, function() {
  'use strict'
  /*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */

  function safeAdd(x, y) {
    var lsw = (x & 0xffff) + (y & 0xffff)
    var msw = (x >> 16) + (y >> 16) + (lsw >> 16)
    return msw << 16 | lsw & 0xffff
  }

  /*
 * Bitwise rotate a 32-bit number to the left.
 */
  function bitRotateLeft(num, cnt) {
    return num << cnt | num >>> 32 - cnt
  }

  /*
 * These functions implement the four basic operations the algorithm uses.
 */
  function md5cmn(q, a, b, x, s, t) {
    return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b)
  }
  function md5ff(a, b, c, d, x, s, t) {
    return md5cmn(b & c | ~b & d, a, b, x, s, t)
  }
  function md5gg(a, b, c, d, x, s, t) {
    return md5cmn(b & d | c & ~d, a, b, x, s, t)
  }
  function md5hh(a, b, c, d, x, s, t) {
    return md5cmn(b ^ c ^ d, a, b, x, s, t)
  }
  function md5ii(a, b, c, d, x, s, t) {
    return md5cmn(c ^ (b | ~d), a, b, x, s, t)
  }

  /*
 * Calculate the MD5 of an array of little-endian words, and a bit length.
 */
  function binlMD5(x, len) {
    /* append padding */
    x[len >> 5] |= 0x80 << len % 32
    x[(len + 64 >>> 9 << 4) + 14] = len

    var i
    var olda
    var oldb
    var oldc
    var oldd
    var a = 1732584193
    var b = -271733879
    var c = -1732584194
    var d = 271733878

    for (i = 0; i < x.length; i += 16) {
      olda = a
      oldb = b
      oldc = c
      oldd = d

      a = md5ff(a, b, c, d, x[i], 7, -680876936)
      d = md5ff(d, a, b, c, x[i + 1], 12, -389564586)
      c = md5ff(c, d, a, b, x[i + 2], 17, 606105819)
      b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330)
      a = md5ff(a, b, c, d, x[i + 4], 7, -176418897)
      d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426)
      c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341)
      b = md5ff(b, c, d, a, x[i + 7], 22, -45705983)
      a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416)
      d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417)
      c = md5ff(c, d, a, b, x[i + 10], 17, -42063)
      b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162)
      a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682)
      d = md5ff(d, a, b, c, x[i + 13], 12, -40341101)
      c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290)
      b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329)

      a = md5gg(a, b, c, d, x[i + 1], 5, -165796510)
      d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632)
      c = md5gg(c, d, a, b, x[i + 11], 14, 643717713)
      b = md5gg(b, c, d, a, x[i], 20, -373897302)
      a = md5gg(a, b, c, d, x[i + 5], 5, -701558691)
      d = md5gg(d, a, b, c, x[i + 10], 9, 38016083)
      c = md5gg(c, d, a, b, x[i + 15], 14, -660478335)
      b = md5gg(b, c, d, a, x[i + 4], 20, -405537848)
      a = md5gg(a, b, c, d, x[i + 9], 5, 568446438)
      d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690)
      c = md5gg(c, d, a, b, x[i + 3], 14, -187363961)
      b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501)
      a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467)
      d = md5gg(d, a, b, c, x[i + 2], 9, -51403784)
      c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473)
      b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734)

      a = md5hh(a, b, c, d, x[i + 5], 4, -378558)
      d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463)
      c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562)
      b = md5hh(b, c, d, a, x[i + 14], 23, -35309556)
      a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060)
      d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353)
      c = md5hh(c, d, a, b, x[i + 7], 16, -155497632)
      b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640)
      a = md5hh(a, b, c, d, x[i + 13], 4, 681279174)
      d = md5hh(d, a, b, c, x[i], 11, -358537222)
      c = md5hh(c, d, a, b, x[i + 3], 16, -722521979)
      b = md5hh(b, c, d, a, x[i + 6], 23, 76029189)
      a = md5hh(a, b, c, d, x[i + 9], 4, -640364487)
      d = md5hh(d, a, b, c, x[i + 12], 11, -421815835)
      c = md5hh(c, d, a, b, x[i + 15], 16, 530742520)
      b = md5hh(b, c, d, a, x[i + 2], 23, -995338651)

      a = md5ii(a, b, c, d, x[i], 6, -198630844)
      d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415)
      c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905)
      b = md5ii(b, c, d, a, x[i + 5], 21, -57434055)
      a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571)
      d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606)
      c = md5ii(c, d, a, b, x[i + 10], 15, -1051523)
      b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799)
      a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359)
      d = md5ii(d, a, b, c, x[i + 15], 10, -30611744)
      c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380)
      b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649)
      a = md5ii(a, b, c, d, x[i + 4], 6, -145523070)
      d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379)
      c = md5ii(c, d, a, b, x[i + 2], 15, 718787259)
      b = md5ii(b, c, d, a, x[i + 9], 21, -343485551)

      a = safeAdd(a, olda)
      b = safeAdd(b, oldb)
      c = safeAdd(c, oldc)
      d = safeAdd(d, oldd)
    }
    return [a, b, c, d]
  }

  /*
 * Convert an array of little-endian words to a string
 */
  function binl2rstr(input) {
    var i
    var output = ''
    var length32 = input.length * 32
    for (i = 0; i < length32; i += 8) {
      output += String.fromCharCode(input[i >> 5] >>> i % 32 & 0xff)
    }
    return output
  }

  /*
 * Convert a raw string to an array of little-endian words
 * Characters >255 have their high-byte silently ignored.
 */
  function rstr2binl(input) {
    var i
    var output = []
    output[(input.length >> 2) - 1] = undefined
    for (i = 0; i < output.length; i += 1) {
      output[i] = 0
    }
    var length8 = input.length * 8
    for (i = 0; i < length8; i += 8) {
      output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << i % 32
    }
    return output
  }

  /*
 * Calculate the MD5 of a raw string
 */
  function rstrMD5(s) {
    return binl2rstr(binlMD5(rstr2binl(s), s.length * 8))
  }

  /*
 * Calculate the HMAC-MD5, of a key and some data (raw strings)
 */
  function rstrHMACMD5(key, data) {
    var i
    var bkey = rstr2binl(key)
    var ipad = []
    var opad = []
    var hash
    ipad[15] = opad[15] = undefined
    if (bkey.length > 16) {
      bkey = binlMD5(bkey, key.length * 8)
    }
    for (i = 0; i < 16; i += 1) {
      ipad[i] = bkey[i] ^ 0x36363636
      opad[i] = bkey[i] ^ 0x5c5c5c5c
    }
    hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8)
    return binl2rstr(binlMD5(opad.concat(hash), 512 + 128))
  }

  /*
 * Convert a raw string to a hex string
 */
  function rstr2hex(input) {
    var hexTab = '0123456789abcdef'
    var output = ''
    var x
    var i
    for (i = 0; i < input.length; i += 1) {
      x = input.charCodeAt(i)
      output += hexTab.charAt(x >>> 4 & 0x0f) + hexTab.charAt(x & 0x0f)
    }
    return output
  }

  /*
 * Encode a string as utf-8
 */
  function str2rstrUTF8(input) {
    if (window.unescape) {
      return window.unescape(encodeURIComponent(input))
    }
    return input
  }

  /*
 * Take string arguments and return either raw or hex encoded strings
 */
  function rawMD5(s) {
    return rstrMD5(str2rstrUTF8(s))
  }
  function hexMD5(s) {
    return rstr2hex(rawMD5(s))
  }
  function rawHMACMD5(k, d) {
    return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d))
  }
  function hexHMACMD5(k, d) {
    return rstr2hex(rawHMACMD5(k, d))
  }

  function md5(string, key, raw) {
    if (!key) {
      if (!raw) {
        return hexMD5(string)
      }
      return rawMD5(string)
    }
    if (!raw) {
      return hexHMACMD5(key, string)
    }
    return rawHMACMD5(key, string)
  }

  return {
    MD5: md5,
    RawMD5: rstrMD5
  }
});
/* axios v0.19.0 | (c) 2019 by Matt Zabriskie */
(function webpackUniversalModuleDefinition(root, factory) {
  if (typeof define === 'function' && define.amd) {
    define('axios', [], factory)
  } else {
    root['axios'] = factory()
  }
})(undefined || window, function() {
  return (/** ****/function(modules) {
    // webpackBootstrap
    /** ****/ // The module cache
    /** ****/var installedModules = {}
    /** ****/
    /** ****/ // The require function
    /** ****/function __webpack_require__(moduleId) {
      /** ****/
      /** ****/ // Check if module is in cache
      /** ****/if (installedModules[moduleId])
      /** ****/{ return installedModules[moduleId].exports }
      /** ****/
      /** ****/ // Create a new module (and put it into the cache)
      /** ****/var module = installedModules[moduleId] = {
        /** ****/exports: {},
        /** ****/id: moduleId,
        /** ****/loaded: false
        /** ****/ }
      /** ****/
      /** ****/ // Execute the module function
      /** ****/modules[moduleId].call(module.exports, module, module.exports, __webpack_require__)
      /** ****/
      /** ****/ // Flag the module as loaded
      /** ****/module.loaded = true
      /** ****/
      /** ****/ // Return the exports of the module
      /** ****/return module.exports
      /** ****/
    }
    /** ****/
    /** ****/
    /** ****/ // expose the modules object (__webpack_modules__)
    /** ****/__webpack_require__.m = modules
    /** ****/
    /** ****/ // expose the module cache
    /** ****/__webpack_require__.c = installedModules
    /** ****/
    /** ****/ // __webpack_public_path__
    /** ****/__webpack_require__.p = ''
    /** ****/
    /** ****/ // Load entry module and return exports
    /** ****/return __webpack_require__(0)
    /** ****/
  }(
    /** **********************************************************************/
    /** ****/[
      /* 0 */
      /***/function(module, exports, __webpack_require__) {
        module.exports = __webpack_require__(1)

        /***/
      },
      /* 1 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var utils = __webpack_require__(2)
        var bind = __webpack_require__(3)
        var Axios = __webpack_require__(5)
        var mergeConfig = __webpack_require__(22)
        var defaults = __webpack_require__(11)

        /**
    * Create an instance of Axios
    *
    * @param {Object} defaultConfig The default config for the instance
    * @return {Axios} A new instance of Axios
    */
        function createInstance(defaultConfig) {
          var context = new Axios(defaultConfig)
          var instance = bind(Axios.prototype.request, context)

          // Copy axios.prototype to instance
          utils.extend(instance, Axios.prototype, context)

          // Copy context to instance
          utils.extend(instance, context)

          return instance
        }

        // Create the default instance to be exported
        var axios = createInstance(defaults)

        // Expose Axios class to allow class inheritance
        axios.Axios = Axios

        // Factory for creating new instances
        axios.create = function create(instanceConfig) {
          return createInstance(mergeConfig(axios.defaults, instanceConfig))
        }

        // Expose Cancel & CancelToken
        axios.Cancel = __webpack_require__(23)
        axios.CancelToken = __webpack_require__(24)
        axios.isCancel = __webpack_require__(10)

        // Expose all/spread
        axios.all = function all(promises) {
          return Promise.all(promises)
        }
        axios.spread = __webpack_require__(25)

        module.exports = axios

        // Allow use of default import syntax in TypeScript
        module.exports.default = axios

        /***/
      },
      /* 2 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var bind = __webpack_require__(3)
        var isBuffer = __webpack_require__(4)

        /*global toString:true*/

        // utils is a library of generic helper functions non-specific to axios

        var toString = Object.prototype.toString

        /**
    * Determine if a value is an Array
    *
    * @param {Object} val The value to test
    * @returns {boolean} True if value is an Array, otherwise false
    */
        function isArray(val) {
          return toString.call(val) === '[object Array]'
        }

        /**
    * Determine if a value is an ArrayBuffer
    *
    * @param {Object} val The value to test
    * @returns {boolean} True if value is an ArrayBuffer, otherwise false
    */
        function isArrayBuffer(val) {
          return toString.call(val) === '[object ArrayBuffer]'
        }

        /**
    * Determine if a value is a FormData
    *
    * @param {Object} val The value to test
    * @returns {boolean} True if value is an FormData, otherwise false
    */
        function isFormData(val) {
          return typeof FormData !== 'undefined' && val instanceof FormData
        }

        /**
    * Determine if a value is a view on an ArrayBuffer
    *
    * @param {Object} val The value to test
    * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false
    */
        function isArrayBufferView(val) {
          var result
          if (typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView) {
            result = ArrayBuffer.isView(val)
          } else {
            result = val && val.buffer && val.buffer instanceof ArrayBuffer
          }
          return result
        }

        /**
    * Determine if a value is a String
    *
    * @param {Object} val The value to test
    * @returns {boolean} True if value is a String, otherwise false
    */
        function isString(val) {
          return typeof val === 'string'
        }

        /**
    * Determine if a value is a Number
    *
    * @param {Object} val The value to test
    * @returns {boolean} True if value is a Number, otherwise false
    */
        function isNumber(val) {
          return typeof val === 'number'
        }

        /**
    * Determine if a value is undefined
    *
    * @param {Object} val The value to test
    * @returns {boolean} True if the value is undefined, otherwise false
    */
        function isUndefined(val) {
          return typeof val === 'undefined'
        }

        /**
    * Determine if a value is an Object
    *
    * @param {Object} val The value to test
    * @returns {boolean} True if value is an Object, otherwise false
    */
        function isObject(val) {
          return val !== null && (typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object'
        }

        /**
    * Determine if a value is a Date
    *
    * @param {Object} val The value to test
    * @returns {boolean} True if value is a Date, otherwise false
    */
        function isDate(val) {
          return toString.call(val) === '[object Date]'
        }

        /**
    * Determine if a value is a File
    *
    * @param {Object} val The value to test
    * @returns {boolean} True if value is a File, otherwise false
    */
        function isFile(val) {
          return toString.call(val) === '[object File]'
        }

        /**
    * Determine if a value is a Blob
    *
    * @param {Object} val The value to test
    * @returns {boolean} True if value is a Blob, otherwise false
    */
        function isBlob(val) {
          return toString.call(val) === '[object Blob]'
        }

        /**
    * Determine if a value is a Function
    *
    * @param {Object} val The value to test
    * @returns {boolean} True if value is a Function, otherwise false
    */
        function isFunction(val) {
          return toString.call(val) === '[object Function]'
        }

        /**
    * Determine if a value is a Stream
    *
    * @param {Object} val The value to test
    * @returns {boolean} True if value is a Stream, otherwise false
    */
        function isStream(val) {
          return isObject(val) && isFunction(val.pipe)
        }

        /**
    * Determine if a value is a URLSearchParams object
    *
    * @param {Object} val The value to test
    * @returns {boolean} True if value is a URLSearchParams object, otherwise false
    */
        function isURLSearchParams(val) {
          return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
        }

        /**
    * Trim excess whitespace off the beginning and end of a string
    *
    * @param {String} str The String to trim
    * @returns {String} The String freed of excess whitespace
    */
        function trim(str) {
          return str.replace(/^\s*/, '').replace(/\s*$/, '')
        }

        /**
    * Determine if we're running in a standard browser environment
    *
    * This allows axios to run in a web worker, and react-native.
    * Both environments support XMLHttpRequest, but not fully standard globals.
    *
    * web workers:
    *  typeof window -> undefined
    *  typeof document -> undefined
    *
    * react-native:
    *  navigator.product -> 'ReactNative'
    * nativescript
    *  navigator.product -> 'NativeScript' or 'NS'
    */
        function isStandardBrowserEnv() {
          if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' || navigator.product === 'NativeScript' || navigator.product === 'NS')) {
            return false
          }
          return typeof window !== 'undefined' && typeof document !== 'undefined'
        }

        /**
    * Iterate over an Array or an Object invoking a function for each item.
    *
    * If `obj` is an Array callback will be called passing
    * the value, index, and complete array for each item.
    *
    * If 'obj' is an Object callback will be called passing
    * the value, key, and complete object for each property.
    *
    * @param {Object|Array} obj The object to iterate
    * @param {Function} fn The callback to invoke for each item
    */
        function forEach(obj, fn) {
          // Don't bother if no value provided
          if (obj === null || typeof obj === 'undefined') {
            return
          }

          // Force an array if not already something iterable
          if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object') {
            /*eslint no-param-reassign:0*/
            obj = [obj]
          }

          if (isArray(obj)) {
            // Iterate over array values
            for (var i = 0, l = obj.length; i < l; i++) {
              fn.call(null, obj[i], i, obj)
            }
          } else {
            // Iterate over object keys
            for (var key in obj) {
              if (Object.prototype.hasOwnProperty.call(obj, key)) {
                fn.call(null, obj[key], key, obj)
              }
            }
          }
        }

        /**
    * Accepts varargs expecting each argument to be an object, then
    * immutably merges the properties of each object and returns result.
    *
    * When multiple objects contain the same key the later object in
    * the arguments list will take precedence.
    *
    * Example:
    *
    * ```js
    * var result = merge({foo: 123}, {foo: 456});
    * console.log(result.foo); // outputs 456
    * ```
    *
    * @param {Object} obj1 Object to merge
    * @returns {Object} Result of all merge properties
    */
        function merge() /* obj1, obj2, obj3, ... */{
          var result = {}
          function assignValue(val, key) {
            if (_typeof(result[key]) === 'object' && (typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object') {
              result[key] = merge(result[key], val)
            } else {
              result[key] = val
            }
          }

          for (var i = 0, l = arguments.length; i < l; i++) {
            forEach(arguments[i], assignValue)
          }
          return result
        }

        /**
    * Function equal to merge with the difference being that no reference
    * to original objects is kept.
    *
    * @see merge
    * @param {Object} obj1 Object to merge
    * @returns {Object} Result of all merge properties
    */
        function deepMerge() /* obj1, obj2, obj3, ... */{
          var result = {}
          function assignValue(val, key) {
            if (_typeof(result[key]) === 'object' && (typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object') {
              result[key] = deepMerge(result[key], val)
            } else if ((typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object') {
              result[key] = deepMerge({}, val)
            } else {
              result[key] = val
            }
          }

          for (var i = 0, l = arguments.length; i < l; i++) {
            forEach(arguments[i], assignValue)
          }
          return result
        }

        /**
    * Extends object a by mutably adding to it the properties of object b.
    *
    * @param {Object} a The object to be extended
    * @param {Object} b The object to copy properties from
    * @param {Object} thisArg The object to bind function to
    * @return {Object} The resulting value of object a
    */
        function extend(a, b, thisArg) {
          forEach(b, function assignValue(val, key) {
            if (thisArg && typeof val === 'function') {
              a[key] = bind(val, thisArg)
            } else {
              a[key] = val
            }
          })
          return a
        }

        module.exports = {
          isArray: isArray,
          isArrayBuffer: isArrayBuffer,
          isBuffer: isBuffer,
          isFormData: isFormData,
          isArrayBufferView: isArrayBufferView,
          isString: isString,
          isNumber: isNumber,
          isObject: isObject,
          isUndefined: isUndefined,
          isDate: isDate,
          isFile: isFile,
          isBlob: isBlob,
          isFunction: isFunction,
          isStream: isStream,
          isURLSearchParams: isURLSearchParams,
          isStandardBrowserEnv: isStandardBrowserEnv,
          forEach: forEach,
          merge: merge,
          deepMerge: deepMerge,
          extend: extend,
          trim: trim
        }

        /***/
      },
      /* 3 */
      /***/function(module, exports) {
        'use strict'

        module.exports = function bind(fn, thisArg) {
          return function wrap() {
            var args = new Array(arguments.length)
            for (var i = 0; i < args.length; i++) {
              args[i] = arguments[i]
            }
            return fn.apply(thisArg, args)
          }
        }

        /***/
      },
      /* 4 */
      /***/function(module, exports) {
        /*!
    * Determine if an object is a Buffer
    *
    * @author   Feross Aboukhadijeh <https://feross.org>
    * @license  MIT
    */

        module.exports = function isBuffer(obj) {
          return obj != null && obj.constructor != null && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
        }

        /***/
      },
      /* 5 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var utils = __webpack_require__(2)
        var buildURL = __webpack_require__(6)
        var InterceptorManager = __webpack_require__(7)
        var dispatchRequest = __webpack_require__(8)
        var mergeConfig = __webpack_require__(22)

        /**
    * Create a new instance of Axios
    *
    * @param {Object} instanceConfig The default config for the instance
    */
        function Axios(instanceConfig) {
          this.defaults = instanceConfig
          this.interceptors = {
            request: new InterceptorManager(),
            response: new InterceptorManager()
          }
        }

        /**
    * Dispatch a request
    *
    * @param {Object} config The config specific for this request (merged with this.defaults)
    */
        Axios.prototype.request = function request(config) {
          /*eslint no-param-reassign:0*/
          // Allow for axios('example/url'[, config]) a la fetch API
          if (typeof config === 'string') {
            config = arguments[1] || {}
            config.url = arguments[0]
          } else {
            config = config || {}
          }

          config = mergeConfig(this.defaults, config)
          config.method = config.method ? config.method.toLowerCase() : 'get'

          // Hook up interceptors middleware
          var chain = [dispatchRequest, undefined]
          var promise = Promise.resolve(config)

          this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
            chain.unshift(interceptor.fulfilled, interceptor.rejected)
          })

          this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
            chain.push(interceptor.fulfilled, interceptor.rejected)
          })

          while (chain.length) {
            promise = promise.then(chain.shift(), chain.shift())
          }

          return promise
        }

        Axios.prototype.getUri = function getUri(config) {
          config = mergeConfig(this.defaults, config)
          return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\?/, '')
        }

        // Provide aliases for supported request methods
        utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
          /*eslint func-names:0*/
          Axios.prototype[method] = function(url, config) {
            return this.request(utils.merge(config || {}, {
              method: method,
              url: url
            }))
          }
        })

        utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
          /*eslint func-names:0*/
          Axios.prototype[method] = function(url, data, config) {
            return this.request(utils.merge(config || {}, {
              method: method,
              url: url,
              data: data
            }))
          }
        })

        module.exports = Axios

        /***/
      },
      /* 6 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var utils = __webpack_require__(2)

        function encode(val) {
          return encodeURIComponent(val).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']')
        }

        /**
    * Build a URL by appending params to the end
    *
    * @param {string} url The base of the url (e.g., http://www.google.com)
    * @param {object} [params] The params to be appended
    * @returns {string} The formatted url
    */
        module.exports = function buildURL(url, params, paramsSerializer) {
          /*eslint no-param-reassign:0*/
          if (!params) {
            return url
          }

          var serializedParams
          if (paramsSerializer) {
            serializedParams = paramsSerializer(params)
          } else if (utils.isURLSearchParams(params)) {
            serializedParams = params.toString()
          } else {
            var parts = []

            utils.forEach(params, function serialize(val, key) {
              if (val === null || typeof val === 'undefined') {
                return
              }

              if (utils.isArray(val)) {
                key = key + '[]'
              } else {
                val = [val]
              }

              utils.forEach(val, function parseValue(v) {
                if (utils.isDate(v)) {
                  v = v.toISOString()
                } else if (utils.isObject(v)) {
                  v = JSON.stringify(v)
                }
                parts.push(encode(key) + '=' + encode(v))
              })
            })

            serializedParams = parts.join('&')
          }

          if (serializedParams) {
            var hashmarkIndex = url.indexOf('#')
            if (hashmarkIndex !== -1) {
              url = url.slice(0, hashmarkIndex)
            }

            url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
          }

          return url
        }

        /***/
      },
      /* 7 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var utils = __webpack_require__(2)

        function InterceptorManager() {
          this.handlers = []
        }

        /**
    * Add a new interceptor to the stack
    *
    * @param {Function} fulfilled The function to handle `then` for a `Promise`
    * @param {Function} rejected The function to handle `reject` for a `Promise`
    *
    * @return {Number} An ID used to remove interceptor later
    */
        InterceptorManager.prototype.use = function use(fulfilled, rejected) {
          this.handlers.push({
            fulfilled: fulfilled,
            rejected: rejected
          })
          return this.handlers.length - 1
        }

        /**
    * Remove an interceptor from the stack
    *
    * @param {Number} id The ID that was returned by `use`
    */
        InterceptorManager.prototype.eject = function eject(id) {
          if (this.handlers[id]) {
            this.handlers[id] = null
          }
        }

        /**
    * Iterate over all the registered interceptors
    *
    * This method is particularly useful for skipping over any
    * interceptors that may have become `null` calling `eject`.
    *
    * @param {Function} fn The function to call for each interceptor
    */
        InterceptorManager.prototype.forEach = function forEach(fn) {
          utils.forEach(this.handlers, function forEachHandler(h) {
            if (h !== null) {
              fn(h)
            }
          })
        }

        module.exports = InterceptorManager

        /***/
      },
      /* 8 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var utils = __webpack_require__(2)
        var transformData = __webpack_require__(9)
        var isCancel = __webpack_require__(10)
        var defaults = __webpack_require__(11)
        var isAbsoluteURL = __webpack_require__(20)
        var combineURLs = __webpack_require__(21)

        /**
    * Throws a `Cancel` if cancellation has been requested.
    */
        function throwIfCancellationRequested(config) {
          if (config.cancelToken) {
            config.cancelToken.throwIfRequested()
          }
        }

        /**
    * Dispatch a request to the server using the configured adapter.
    *
    * @param {object} config The config that is to be used for the request
    * @returns {Promise} The Promise to be fulfilled
    */
        module.exports = function dispatchRequest(config) {
          throwIfCancellationRequested(config)

          // Support baseURL config
          if (config.baseURL && !isAbsoluteURL(config.url)) {
            config.url = combineURLs(config.baseURL, config.url)
          }

          // Ensure headers exist
          config.headers = config.headers || {}

          // Transform request data
          config.data = transformData(config.data, config.headers, config.transformRequest)

          // Flatten headers
          config.headers = utils.merge(config.headers.common || {}, config.headers[config.method] || {}, config.headers || {})

          utils.forEach(['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], function cleanHeaderConfig(method) {
            delete config.headers[method]
          })

          var adapter = config.adapter || defaults.adapter

          return adapter(config).then(function onAdapterResolution(response) {
            throwIfCancellationRequested(config)

            // Transform response data
            response.data = transformData(response.data, response.headers, config.transformResponse)

            return response
          }, function onAdapterRejection(reason) {
            if (!isCancel(reason)) {
              throwIfCancellationRequested(config)

              // Transform response data
              if (reason && reason.response) {
                reason.response.data = transformData(reason.response.data, reason.response.headers, config.transformResponse)
              }
            }

            return Promise.reject(reason)
          })
        }

        /***/
      },
      /* 9 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var utils = __webpack_require__(2)

        /**
    * Transform the data for a request or a response
    *
    * @param {Object|String} data The data to be transformed
    * @param {Array} headers The headers for the request or response
    * @param {Array|Function} fns A single function or Array of functions
    * @returns {*} The resulting transformed data
    */
        module.exports = function transformData(data, headers, fns) {
          /*eslint no-param-reassign:0*/
          utils.forEach(fns, function transform(fn) {
            data = fn(data, headers)
          })

          return data
        }

        /***/
      },
      /* 10 */
      /***/function(module, exports) {
        'use strict'

        module.exports = function isCancel(value) {
          return !!(value && value.__CANCEL__)
        }

        /***/
      },
      /* 11 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var utils = __webpack_require__(2)
        var normalizeHeaderName = __webpack_require__(12)

        var DEFAULT_CONTENT_TYPE = {
          'Content-Type': 'application/x-www-form-urlencoded'
        }

        function setContentTypeIfUnset(headers, value) {
          if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {
            headers['Content-Type'] = value
          }
        }

        function getDefaultAdapter() {
          var adapter
          // Only Node.JS has a process variable that is of [[Class]] process
          if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
            // For node use HTTP adapter
            adapter = __webpack_require__(13)
          } else if (typeof XMLHttpRequest !== 'undefined') {
            // For browsers use XHR adapter
            adapter = __webpack_require__(13)
          }
          return adapter
        }

        var defaults = {
          adapter: getDefaultAdapter(),

          transformRequest: [function transformRequest(data, headers) {
            normalizeHeaderName(headers, 'Accept')
            normalizeHeaderName(headers, 'Content-Type')
            if (utils.isFormData(data) || utils.isArrayBuffer(data) || utils.isBuffer(data) || utils.isStream(data) || utils.isFile(data) || utils.isBlob(data)) {
              return data
            }
            if (utils.isArrayBufferView(data)) {
              return data.buffer
            }
            if (utils.isURLSearchParams(data)) {
              setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8')
              return data.toString()
            }
            if (utils.isObject(data)) {
              setContentTypeIfUnset(headers, 'application/json;charset=utf-8')
              return JSON.stringify(data)
            }
            return data
          }],

          transformResponse: [function transformResponse(data) {
            /*eslint no-param-reassign:0*/
            if (typeof data === 'string') {
              try {
                data = JSON.parse(data)
              } catch (e) { /* Ignore */ }
            }
            return data
          }],

          /**
     * A timeout in milliseconds to abort a request. If set to 0 (default) a
     * timeout is not created.
     */
          timeout: 0,

          xsrfCookieName: 'XSRF-TOKEN',
          xsrfHeaderName: 'X-XSRF-TOKEN',

          maxContentLength: -1,

          validateStatus: function validateStatus(status) {
            return status >= 200 && status < 300
          }
        }

        defaults.headers = {
          common: {
            'Accept': 'application/json, text/plain, */*'
          }
        }

        utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {
          defaults.headers[method] = {}
        })

        utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
          defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE)
        })

        module.exports = defaults

        /***/
      },
      /* 12 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var utils = __webpack_require__(2)

        module.exports = function normalizeHeaderName(headers, normalizedName) {
          utils.forEach(headers, function processHeader(value, name) {
            if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {
              headers[normalizedName] = value
              delete headers[name]
            }
          })
        }

        /***/
      },
      /* 13 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var utils = __webpack_require__(2)
        var settle = __webpack_require__(14)
        var buildURL = __webpack_require__(6)
        var parseHeaders = __webpack_require__(17)
        var isURLSameOrigin = __webpack_require__(18)
        var createError = __webpack_require__(15)

        module.exports = function xhrAdapter(config) {
          return new Promise(function dispatchXhrRequest(resolve, reject) {
            var requestData = config.data
            var requestHeaders = config.headers

            if (utils.isFormData(requestData)) {
              delete requestHeaders['Content-Type'] // Let the browser set it
            }

            var request = new XMLHttpRequest()

            // HTTP basic authentication
            if (config.auth) {
              var username = config.auth.username || ''
              var password = config.auth.password || ''
              requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password)
            }

            request.open(config.method.toUpperCase(), buildURL(config.url, config.params, config.paramsSerializer), true)

            // Set the request timeout in MS
            request.timeout = config.timeout

            // Listen for ready state
            request.onreadystatechange = function handleLoad() {
              if (!request || request.readyState !== 4) {
                return
              }

              // The request errored out and we didn't get a response, this will be
              // handled by onerror instead
              // With one exception: request that using file: protocol, most browsers
              // will return status as 0 even though it's a successful request
              if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {
                return
              }

              // Prepare the response
              var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null
              var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response
              var response = {
                data: responseData,
                status: request.status,
                statusText: request.statusText,
                headers: responseHeaders,
                config: config,
                request: request
              }

              settle(resolve, reject, response)

              // Clean up request
              request = null
            }

            // Handle browser request cancellation (as opposed to a manual cancellation)
            request.onabort = function handleAbort() {
              if (!request) {
                return
              }

              reject(createError('Request aborted', config, 'ECONNABORTED', request))

              // Clean up request
              request = null
            }

            // Handle low level network errors
            request.onerror = function handleError() {
              // Real errors are hidden from us by the browser
              // onerror should only fire if it's a network error
              reject(createError('Network Error', config, null, request))

              // Clean up request
              request = null
            }

            // Handle timeout
            request.ontimeout = function handleTimeout() {
              reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', request))

              // Clean up request
              request = null
            }

            // Add xsrf header
            // This is only done if running in a standard browser environment.
            // Specifically not if we're in a web worker, or react-native.
            if (utils.isStandardBrowserEnv()) {
              var cookies = __webpack_require__(19)

              // Add xsrf header
              var xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ? cookies.read(config.xsrfCookieName) : undefined

              if (xsrfValue) {
                requestHeaders[config.xsrfHeaderName] = xsrfValue
              }
            }

            // Add headers to the request
            if ('setRequestHeader' in request) {
              utils.forEach(requestHeaders, function setRequestHeader(val, key) {
                if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {
                  // Remove Content-Type if data is undefined
                  delete requestHeaders[key]
                } else {
                  // Otherwise add header to the request
                  request.setRequestHeader(key, val)
                }
              })
            }

            // Add withCredentials to request if needed
            if (config.withCredentials) {
              request.withCredentials = true
            }

            // Add responseType to request if needed
            if (config.responseType) {
              try {
                request.responseType = config.responseType
              } catch (e) {
                // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2.
                // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function.
                if (config.responseType !== 'json') {
                  throw e
                }
              }
            }

            // Handle progress if needed
            if (typeof config.onDownloadProgress === 'function') {
              request.addEventListener('progress', config.onDownloadProgress)
            }

            // Not all browsers support upload events
            if (typeof config.onUploadProgress === 'function' && request.upload) {
              request.upload.addEventListener('progress', config.onUploadProgress)
            }

            if (config.cancelToken) {
              // Handle cancellation
              config.cancelToken.promise.then(function onCanceled(cancel) {
                if (!request) {
                  return
                }

                request.abort()
                reject(cancel)
                // Clean up request
                request = null
              })
            }

            if (requestData === undefined) {
              requestData = null
            }

            // Send the request
            request.send(requestData)
          })
        }

        /***/
      },
      /* 14 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var createError = __webpack_require__(15)

        /**
    * Resolve or reject a Promise based on response status.
    *
    * @param {Function} resolve A function that resolves the promise.
    * @param {Function} reject A function that rejects the promise.
    * @param {object} response The response.
    */
        module.exports = function settle(resolve, reject, response) {
          var validateStatus = response.config.validateStatus
          if (!validateStatus || validateStatus(response.status)) {
            resolve(response)
          } else {
            reject(createError('Request failed with status code ' + response.status, response.config, null, response.request, response))
          }
        }

        /***/
      },
      /* 15 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var enhanceError = __webpack_require__(16)

        /**
    * Create an Error with the specified message, config, error code, request and response.
    *
    * @param {string} message The error message.
    * @param {Object} config The config.
    * @param {string} [code] The error code (for example, 'ECONNABORTED').
    * @param {Object} [request] The request.
    * @param {Object} [response] The response.
    * @returns {Error} The created error.
    */
        module.exports = function createError(message, config, code, request, response) {
          var error = new Error(message)
          return enhanceError(error, config, code, request, response)
        }

        /***/
      },
      /* 16 */
      /***/function(module, exports) {
        'use strict'

        /**
    * Update an Error with the specified config, error code, and response.
    *
    * @param {Error} error The error to update.
    * @param {Object} config The config.
    * @param {string} [code] The error code (for example, 'ECONNABORTED').
    * @param {Object} [request] The request.
    * @param {Object} [response] The response.
    * @returns {Error} The error.
    */

        module.exports = function enhanceError(error, config, code, request, response) {
          error.config = config
          if (code) {
            error.code = code
          }

          error.request = request
          error.response = response
          error.isAxiosError = true

          error.toJSON = function() {
            return {
              // Standard
              message: this.message,
              name: this.name,
              // Microsoft
              description: this.description,
              number: this.number,
              // Mozilla
              fileName: this.fileName,
              lineNumber: this.lineNumber,
              columnNumber: this.columnNumber,
              stack: this.stack,
              // Axios
              config: this.config,
              code: this.code
            }
          }
          return error
        }

        /***/
      },
      /* 17 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var utils = __webpack_require__(2)

        // Headers whose duplicates are ignored by node
        // c.f. https://nodejs.org/api/http.html#http_message_headers
        var ignoreDuplicateOf = ['age', 'authorization', 'content-length', 'content-type', 'etag', 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since', 'last-modified', 'location', 'max-forwards', 'proxy-authorization', 'referer', 'retry-after', 'user-agent']

        /**
    * Parse headers into an object
    *
    * ```
    * Date: Wed, 27 Aug 2014 08:58:49 GMT
    * Content-Type: application/json
    * Connection: keep-alive
    * Transfer-Encoding: chunked
    * ```
    *
    * @param {String} headers Headers needing to be parsed
    * @returns {Object} Headers parsed into an object
    */
        module.exports = function parseHeaders(headers) {
          var parsed = {}
          var key
          var val
          var i

          if (!headers) {
            return parsed
          }

          utils.forEach(headers.split('\n'), function parser(line) {
            i = line.indexOf(':')
            key = utils.trim(line.substr(0, i)).toLowerCase()
            val = utils.trim(line.substr(i + 1))

            if (key) {
              if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) {
                return
              }
              if (key === 'set-cookie') {
                parsed[key] = (parsed[key] ? parsed[key] : []).concat([val])
              } else {
                parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val
              }
            }
          })

          return parsed
        }

        /***/
      },
      /* 18 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var utils = __webpack_require__(2)

        module.exports = utils.isStandardBrowserEnv()

        // Standard browser envs have full support of the APIs needed to test
        // whether the request URL is of the same origin as current location.
          ? (function standardBrowserEnv() {
            var msie = /(msie|trident)/i.test(navigator.userAgent)
            var urlParsingNode = document.createElement('a')
            var originURL

            /**
    * Parse a URL to discover it's components
    *
    * @param {String} url The URL to be parsed
    * @returns {Object}
    */
            function resolveURL(url) {
              var href = url

              if (msie) {
                // IE needs attribute set twice to normalize properties
                urlParsingNode.setAttribute('href', href)
                href = urlParsingNode.href
              }

              urlParsingNode.setAttribute('href', href)

              // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
              return {
                href: urlParsingNode.href,
                protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
                host: urlParsingNode.host,
                search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
                hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
                hostname: urlParsingNode.hostname,
                port: urlParsingNode.port,
                pathname: urlParsingNode.pathname.charAt(0) === '/' ? urlParsingNode.pathname : '/' + urlParsingNode.pathname
              }
            }

            originURL = resolveURL(window.location.href)

            /**
    * Determine if a URL shares the same origin as the current location
    *
    * @param {String} requestURL The URL to test
    * @returns {boolean} True if URL shares the same origin, otherwise false
    */
            return function isURLSameOrigin(requestURL) {
              var parsed = utils.isString(requestURL) ? resolveURL(requestURL) : requestURL
              return parsed.protocol === originURL.protocol && parsed.host === originURL.host
            }
          }())

        // Non standard browser envs (web workers, react-native) lack needed support.
          : (function nonStandardBrowserEnv() {
            return function isURLSameOrigin() {
              return true
            }
          }())

        /***/
      },
      /* 19 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var utils = __webpack_require__(2)

        module.exports = utils.isStandardBrowserEnv()

        // Standard browser envs support document.cookie
          ? (function standardBrowserEnv() {
            return {
              write: function write(name, value, expires, path, domain, secure) {
                var cookie = []
                cookie.push(name + '=' + encodeURIComponent(value))

                if (utils.isNumber(expires)) {
                  cookie.push('expires=' + new Date(expires).toGMTString())
                }

                if (utils.isString(path)) {
                  cookie.push('path=' + path)
                }

                if (utils.isString(domain)) {
                  cookie.push('domain=' + domain)
                }

                if (secure === true) {
                  cookie.push('secure')
                }

                document.cookie = cookie.join('; ')
              },

              read: function read(name) {
                var match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)'))
                return match ? decodeURIComponent(match[3]) : null
              },

              remove: function remove(name) {
                this.write(name, '', Date.now() - 86400000)
              }
            }
          }())

        // Non standard browser env (web workers, react-native) lack needed support.
          : (function nonStandardBrowserEnv() {
            return {
              write: function write() {},
              read: function read() {
                return null
              },
              remove: function remove() {}
            }
          }())

        /***/
      },
      /* 20 */
      /***/function(module, exports) {
        'use strict'

        /**
    * Determines whether the specified URL is absolute
    *
    * @param {string} url The URL to test
    * @returns {boolean} True if the specified URL is absolute, otherwise false
    */

        module.exports = function isAbsoluteURL(url) {
          // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
          // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
          // by any combination of letters, digits, plus, period, or hyphen.
          return (/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url)
          )
        }

        /***/
      },
      /* 21 */
      /***/function(module, exports) {
        'use strict'

        /**
    * Creates a new URL by combining the specified URLs
    *
    * @param {string} baseURL The base URL
    * @param {string} relativeURL The relative URL
    * @returns {string} The combined URL
    */

        module.exports = function combineURLs(baseURL, relativeURL) {
          return relativeURL ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') : baseURL
        }

        /***/
      },
      /* 22 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var utils = __webpack_require__(2)

        /**
    * Config-specific merge-function which creates a new config-object
    * by merging two configuration objects together.
    *
    * @param {Object} config1
    * @param {Object} config2
    * @returns {Object} New object resulting from merging config2 to config1
    */
        module.exports = function mergeConfig(config1, config2) {
          // eslint-disable-next-line no-param-reassign
          config2 = config2 || {}
          var config = {}

          utils.forEach(['url', 'method', 'params', 'data'], function valueFromConfig2(prop) {
            if (typeof config2[prop] !== 'undefined') {
              config[prop] = config2[prop]
            }
          })

          utils.forEach(['headers', 'auth', 'proxy'], function mergeDeepProperties(prop) {
            if (utils.isObject(config2[prop])) {
              config[prop] = utils.deepMerge(config1[prop], config2[prop])
            } else if (typeof config2[prop] !== 'undefined') {
              config[prop] = config2[prop]
            } else if (utils.isObject(config1[prop])) {
              config[prop] = utils.deepMerge(config1[prop])
            } else if (typeof config1[prop] !== 'undefined') {
              config[prop] = config1[prop]
            }
          })

          utils.forEach(['baseURL', 'transformRequest', 'transformResponse', 'paramsSerializer', 'timeout', 'withCredentials', 'adapter', 'responseType', 'xsrfCookieName', 'xsrfHeaderName', 'onUploadProgress', 'onDownloadProgress', 'maxContentLength', 'validateStatus', 'maxRedirects', 'httpAgent', 'httpsAgent', 'cancelToken', 'socketPath'], function defaultToConfig2(prop) {
            if (typeof config2[prop] !== 'undefined') {
              config[prop] = config2[prop]
            } else if (typeof config1[prop] !== 'undefined') {
              config[prop] = config1[prop]
            }
          })

          return config
        }

        /***/
      },
      /* 23 */
      /***/function(module, exports) {
        'use strict'

        /**
    * A `Cancel` is an object that is thrown when an operation is canceled.
    *
    * @class
    * @param {string=} message The message.
    */

        function Cancel(message) {
          this.message = message
        }

        Cancel.prototype.toString = function toString() {
          return 'Cancel' + (this.message ? ': ' + this.message : '')
        }

        Cancel.prototype.__CANCEL__ = true

        module.exports = Cancel

        /***/
      },
      /* 24 */
      /***/function(module, exports, __webpack_require__) {
        'use strict'

        var Cancel = __webpack_require__(23)

        /**
    * A `CancelToken` is an object that can be used to request cancellation of an operation.
    *
    * @class
    * @param {Function} executor The executor function.
    */
        function CancelToken(executor) {
          if (typeof executor !== 'function') {
            throw new TypeError('executor must be a function.')
          }

          var resolvePromise
          this.promise = new Promise(function promiseExecutor(resolve) {
            resolvePromise = resolve
          })

          var token = this
          executor(function cancel(message) {
            if (token.reason) {
              // Cancellation has already been requested
              return
            }

            token.reason = new Cancel(message)
            resolvePromise(token.reason)
          })
        }

        /**
    * Throws a `Cancel` if cancellation has been requested.
    */
        CancelToken.prototype.throwIfRequested = function throwIfRequested() {
          if (this.reason) {
            throw this.reason
          }
        }

        /**
    * Returns an object that contains a new `CancelToken` and a function that, when called,
    * cancels the `CancelToken`.
    */
        CancelToken.source = function source() {
          var cancel
          var token = new CancelToken(function executor(c) {
            cancel = c
          })
          return {
            token: token,
            cancel: cancel
          }
        }

        module.exports = CancelToken

        /***/
      },
      /* 25 */
      /***/function(module, exports) {
        'use strict'

        /**
    * Syntactic sugar for invoking a function and expanding an array for arguments.
    *
    * Common use case would be to use `Function.prototype.apply`.
    *
    *  ```js
    *  function f(x, y, z) {}
    *  var args = [1, 2, 3];
    *  f.apply(null, args);
    *  ```
    *
    * With `spread` this example can be re-written.
    *
    *  ```js
    *  spread(function(x, y, z) {})([1, 2, 3]);
    *  ```
    *
    * @param {Function} callback
    * @returns {Function}
    */

        module.exports = function spread(callback) {
          return function wrap(arr) {
            return callback.apply(null, arr)
          }
        }

        /***/
      }]
    /** ****/)
  )
})
;
// # sourceMappingURL=axios.map
/**
 * Copyright 2019 Huawei Technologies Co.,Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
 * this file except in compliance with the License.  You may obtain a copy of the
 * License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 */

(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    define('log', [], factory)
  } else {
    root['log'] = factory()
  }
})(undefined || window, function() {
  var OFF = Number.MAX_VALUE

  var DEBUG = 10

  var INFO = 20

  var WARN = 30

  var ERROR = 40

  function LogUtil() {
    this.consoleLog = window.console
    this._level = OFF
  }

  LogUtil.prototype.setLevel = function(level) {
    if (!level) {
      return
    }
    level = String(level).toLowerCase()
    if (level === 'info') {
      level = INFO
    } else if (level === 'warn') {
      level = WARN
    } else if (level === 'error') {
      level = ERROR
    } else if (level === 'debug') {
      level = DEBUG
    } else {
      level = OFF
    }
    this._level = level
  }

  LogUtil.prototype.runLog = function(level, methodName, msg) {
    if (!level) {
      return
    }
    var form = [new Date().toLocaleString(), level.toLowerCase(), methodName, msg].join('|')
    if (level.toLowerCase() === 'debug' && this._level <= DEBUG) {
      this.consoleLog.debug(form)
    } else if (level.toLowerCase() === 'info' && this._level <= INFO) {
      this.consoleLog.info(form)
    } else if (level.toLowerCase() === 'warn' && this._level <= WARN) {
      this.consoleLog.warn(form)
    } else if (level.toLowerCase() === 'error' && this._level <= ERROR) {
      this.consoleLog.error(form)
    }
  }

  return LogUtil
});

/**
 * Copyright 2019 Huawei Technologies Co.,Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
 * this file except in compliance with the License.  You may obtain a copy of the
 * License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 */
(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    define('v2Model', [], factory)
  } else {
    root['v2Model'] = factory()
  }
})(undefined || window, function() {
  var owner = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'Owner',
    'parameters': {
      'ID': {
        'sentAs': 'ID'
      },
      'Name': {
        'sentAs': 'DisplayName'
      }
    }
  }

  var bucketEncryptionRule = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'Rule',
    'parameters': {
      'ApplyServerSideEncryptionByDefault': {
        'type': 'object',
        'sentAs': 'ApplyServerSideEncryptionByDefault',
        'parameters': {
          'SSEAlgorithm': {
            'sentAs': 'SSEAlgorithm'
          },
          'KMSMasterKeyID': {
            'sentAs': 'KMSMasterKeyID'
          },
          'ProjectID': {
            'sentAs': 'ProjectID'
          }
        }
      }
    }
  }

  var InventoryConfiguration = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'InventoryConfiguration',
    'parameters': {
      'Id': {
        'sentAs': 'Id'

      },
      'IsEnabled': {
        'sentAs': 'IsEnabled'

      },
      'Filter': {
        'type': 'object',
        'sentAs': 'Filter',
        'parameters': {
          'Prefix': {
            'sentAs': 'Prefix'
          }
        }
      },
      'Destination': {
        'type': 'object',
        'sentAs': 'Destination',
        'parameters': {
          'Format': {
            'sentAs': 'Format'
          },
          'Bucket': {
            'sentAs': 'Bucket'
          },
          'Prefix': {
            'sentAs': 'Prefix'
          },
          'Encryption': {
            'type': 'object',
            'sentAs': 'Encryption',
            'parameters': {
              'SSE-KMS': {
                'type': 'object',
                'sentAs': 'SSE-KMS',
                'parameters': {
                  'KeyId': {
                    'sentAs': 'KeyId',
                    'type': 'adapter'
                  }
                }
              }
            }
          }
        }
      },
      'Schedule': {
        'type': 'object',
        'sentAs': 'Schedule',
        'parameters': {
          'Frequency': {
            'sentAs': 'Frequency'
          }
        }
      },
      'IncludedObjectVersions': {
        'sentAs': 'IncludedObjectVersions'
      },
      'OptionalFields': {
        'type': 'object',
        'location': 'xml',
        'sentAs': 'OptionalFields',
        'parameters': {
          'Field': {
            'type': 'array',
            'sentAs': 'Field',
            'items': {
              'type': 'string'
            }
          }
        }
      }
    }
  }

  var initiator = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'Initiator',
    'parameters': {
      'ID': {
        'sentAs': 'ID'
      },
      'Name': {
        'sentAs': 'DisplayName'
      }
    }
  }

  var BackToSourceRules = {
    'sentAs': 'BackToSourceRule',
    'required': true,
    'location': 'xml',
    'type': 'array',
    'items': {
      'type': 'object',
      'parameters': {
        'ID': {
          'sentAs': 'ID'
        },
        'Condition': {
          'sentAs': 'Condition',
          'type': 'object',
          'parameters': {
            'ObjectKeyPrefixEquals': {
              'sentAs': 'ObjectKeyPrefixEquals'
            },
            'HttpErrorCodeReturnedEquals': {
              'sentAs': 'HttpErrorCodeReturnedEquals'
            }
          }
        },
        'Redirect': {
          'sentAs': 'Redirect',
          'type': 'object',
          'parameters': {
            'HttpRedirectCode': {
              'sentAs': 'HttpRedirectCode'
            },
            'SourceEndpoint': {
              'sentAs': 'SourceEndpoint'
            },
            'SourceBucketName': {
              'sentAs': 'SourceBucketName'
            },
            'ReplaceKeyWith': {
              'sentAs': 'ReplaceKeyWith'
            },
            'StaticUri': {
              'sentAs': 'StaticUri'
            },
            'ReplaceKeyPrefixWith': {
              'sentAs': 'ReplaceKeyPrefixWith'
            },
            'MigrationConfiguration': {
              'sentAs': 'MigrationConfiguration',
              'type': 'object',
              'parameters': {
                'Agency': {
                  'sentAs': 'Agency'
                },
                'LogBucketName': {
                  'sentAs': 'LogBucketName'
                },
                'PrivateBucketConfiguration': {
                  'sentAs': 'PrivateBucketConfiguration',
                  'type': 'object',
                  'parameters': {
                    'SourceStorageProvider': {
                      'sentAs': 'SourceStorageProvider'
                    },
                    'SourceBucketAK': {
                      'sentAs': 'SourceBucketAK'
                    },
                    'SourceBucketSK': {
                      'sentAs': 'SourceBucketSK'
                    },
                    'SourceBucketZone': {
                      'sentAs': 'SourceBucketZone'
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  var commonPrefixes = {
    'type': 'array',
    'location': 'xml',
    'sentAs': 'CommonPrefixes',
    'items': {
      'type': 'object',
      'parameters': {
        'Prefix': {
          'decode': true,
          'sentAs': 'Prefix'
        },
        'MTime': {
          'sentAs': 'MTime'
        },
        'InodeNo': {
          'sentAs': 'InodeNo'
        }
      }
    }
  }

  var grants = {
    'type': 'array',
    'location': 'xml',
    'wrapper': 'AccessControlList',
    'sentAs': 'Grant',
    'items': {
      'type': 'object',
      'parameters': {
        'Grantee': {
          'data': {
            'xsiNamespace': 'http://www.w3.org/2001/XMLSchema-instance',
            'xsiType': 'Type'
          },
          'type': 'object',
          'sentAs': 'Grantee',
          'parameters': {
            'Type': {
              'type': 'ignore'
            },
            'ID': {
              'sentAs': 'ID',
              'notAllowEmpty': true
            },
            'Name': {
              'sentAs': 'DisplayName'
            },
            'URI': {
              'sentAs': 'URI',
              'type': 'adapter',
              'notAllowEmpty': true
            }
          }
        },
        'Permission': {
          'sentAs': 'Permission'
        }
      }
    }
  }

  var loggingEnabled = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'LoggingEnabled',
    'parameters': {
      'TargetBucket': {
        'sentAs': 'TargetBucket'
      },
      'TargetPrefix': {
        'sentAs': 'TargetPrefix'
      },
      'TargetGrants': {
        'type': 'array',
        'wrapper': 'TargetGrants',
        'sentAs': 'Grant',
        'items': {
          'type': 'object',
          'parameters': {
            'Grantee': {
              'data': {
                'xsiNamespace': 'http://www.w3.org/2001/XMLSchema-instance',
                'xsiType': 'Type'
              },
              'type': 'object',
              'sentAs': 'Grantee',
              'parameters': {
                'Type': {
                  'type': 'ignore'
                },
                'ID': {
                  'sentAs': 'ID'
                },
                'Name': {
                  'sentAs': 'DisplayName'
                },
                'URI': {
                  'sentAs': 'URI',
                  'type': 'adapter'
                }
              }
            },
            'Permission': {
              'sentAs': 'Permission'
            }
          }
        }
      }
    }
  }

  var rules = {
    'required': true,
    'type': 'array',
    'location': 'xml',
    'sentAs': 'Rule',
    'items': {
      'type': 'object',
      'parameters': {
        'ID': {
          'sentAs': 'ID'
        },
        'Prefix': {
          'sentAs': 'Prefix'
        },
        'Status': {
          'sentAs': 'Status'
        },
        'Transitions': {
          'type': 'array',
          'sentAs': 'Transition',
          'items': {
            'type': 'object',
            'parameters': {
              'StorageClass': {
                'sentAs': 'StorageClass',
                'type': 'adapter'
              },
              'Date': {
                'sentAs': 'Date'
              },
              'Days': {
                'type': 'number',
                'sentAs': 'Days'
              }
            }
          }
        },
        'Expiration': {
          'type': 'object',
          'sentAs': 'Expiration',
          'parameters': {
            'Date': {
              'sentAs': 'Date'
            },
            'Days': {
              'type': 'number',
              'sentAs': 'Days'
            }
          }
        },
        'AbortIncompleteMultipartUpload': {
          'type': 'object',
          'sentAs': 'AbortIncompleteMultipartUpload',
          'parameters': {
            'DaysAfterInitiation': {
              'type': 'number',
              'sentAs': 'DaysAfterInitiation'
            }
          }
        },
        'NoncurrentVersionTransitions': {
          'type': 'array',
          'sentAs': 'NoncurrentVersionTransition',
          'items': {
            'type': 'object',
            'parameters': {
              'StorageClass': {
                'sentAs': 'StorageClass',
                'type': 'adapter'
              },
              'NoncurrentDays': {
                'type': 'number',
                'sentAs': 'NoncurrentDays'
              }
            }
          }
        },
        'NoncurrentVersionExpiration': {
          'type': 'object',
          'sentAs': 'NoncurrentVersionExpiration',
          'parameters': {
            'NoncurrentDays': {
              'type': 'number',
              'sentAs': 'NoncurrentDays'
            }
          }
        }
      }
    }
  }

  var redirectAllRequestsTo = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'RedirectAllRequestsTo',
    'parameters': {
      'HostName': {
        'sentAs': 'HostName'
      },
      'Protocol': {
        'sentAs': 'Protocol'
      }
    }
  }

  var routingRules = {
    'type': 'array',
    'wrapper': 'RoutingRules',
    'location': 'xml',
    'sentAs': 'RoutingRule',
    'items': {
      'type': 'object',
      'parameters': {
        'Condition': {
          'type': 'object',
          'sentAs': 'Condition',
          'parameters': {
            'HttpErrorCodeReturnedEquals': {
              'sentAs': 'HttpErrorCodeReturnedEquals'
            },
            'KeyPrefixEquals': {
              'sentAs': 'KeyPrefixEquals'
            }
          }
        },
        'Redirect': {
          'type': 'object',
          'sentAs': 'Redirect',
          'parameters': {
            'HostName': {
              'sentAs': 'HostName'
            },
            'HttpRedirectCode': {
              'sentAs': 'HttpRedirectCode'
            },
            'Protocol': {
              'sentAs': 'Protocol'
            },
            'ReplaceKeyPrefixWith': {
              'sentAs': 'ReplaceKeyPrefixWith'
            },
            'ReplaceKeyWith': {
              'sentAs': 'ReplaceKeyWith'
            }
          }
        }
      }
    }
  }

  var indexDocument = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'IndexDocument',
    'parameters': {
      'Suffix': {
        'sentAs': 'Suffix'
      }
    }
  }

  var errorDocument = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'ErrorDocument',
    'parameters': {
      'Key': {
        'sentAs': 'Key'
      }
    }
  }

  var corsRule = {
    'required': true,
    'type': 'array',
    'location': 'xml',
    'sentAs': 'CORSRule',
    'items': {
      'type': 'object',
      'parameters': {
        'ID': {
          'sentAs': 'ID'
        },
        'AllowedMethod': {
          'type': 'array',
          'sentAs': 'AllowedMethod',
          'items': {
            'type': 'string'
          }
        },
        'AllowedOrigin': {
          'type': 'array',
          'sentAs': 'AllowedOrigin',
          'items': {
            'type': 'string'
          }
        },
        'AllowedHeader': {
          'type': 'array',
          'sentAs': 'AllowedHeader',
          'items': {
            'type': 'string'
          }
        },
        'MaxAgeSeconds': {
          'type': 'number',
          'sentAs': 'MaxAgeSeconds'
        },
        'ExposeHeader': {
          'type': 'array',
          'sentAs': 'ExposeHeader',
          'items': {
            'type': 'string'
          }
        }
      }
    }
  }

  var functionGraphConfiguration = {
    'type': 'array',
    'location': 'xml',
    'sentAs': 'FunctionGraphConfiguration',
    'items': {
      'type': 'object',
      'location': 'xml',
      'parameters': {
        'ID': {
          'sentAs': 'Id'
        },
        'Filter': {
          'type': 'object',
          'parameters': {
            'FilterRules': {
              'wrapper': 'S3Key',
              'type': 'array',
              'sentAs': 'FilterRule',
              'items': {
                'type': 'object',
                'parameters': {
                  'Name': {},
                  'Value': {}
                }
              }
            }
          }
        },
        'FunctionGraph': {},

        'Event': {
          'type': 'array',
          'items': {
            'type': 'adapter'
          }
        }
      }
    }
  }

  var functionStageConfiguration = {
    'type': 'array',
    'location': 'xml',
    'sentAs': 'FunctionStageConfiguration',
    'items': {
      'type': 'object',
      'location': 'xml',
      'parameters': {
        'ID': {
          'sentAs': 'Id'
        },
        'Filter': {
          'type': 'object',
          'parameters': {
            'FilterRules': {
              'wrapper': 'S3Key',
              'type': 'array',
              'sentAs': 'FilterRule',
              'items': {
                'type': 'object',
                'parameters': {
                  'Name': {},
                  'Value': {}
                }
              }
            }
          }
        },
        'FunctionStage': {},

        'Event': {
          'type': 'array',
          'items': {
            'type': 'adapter'
          }
        }
      }
    }
  }
  var topicConfiguration = {
    'type': 'array',
    'location': 'xml',
    'sentAs': 'TopicConfiguration',
    'items': {
      'type': 'object',
      'location': 'xml',
      'parameters': {
        'ID': {
          'sentAs': 'Id'
        },
        'Filter': {
          'type': 'object',
          'parameters': {
            'FilterRules': {
              'wrapper': 'S3Key',
              'type': 'array',
              'sentAs': 'FilterRule',
              'items': {
                'type': 'object',
                'parameters': {
                  'Name': {},
                  'Value': {}
                }
              }
            }
          }
        },
        'Topic': {},

        'Event': {
          'type': 'array',
          'items': {
            'type': 'adapter'
          }
        }
      }
    }
  }

  var tagSet = {
    'required': true,
    'type': 'array',
    'location': 'xml',
    'wrapper': 'TagSet',
    'sentAs': 'Tag',
    'items': {
      'type': 'object',
      'parameters': {
        'Key': {
          'sentAs': 'Key'
        },
        'Value': {
          'sentAs': 'Value'
        }
      }
    }
  }

  var replicationRules = {
    'required': true,
    'type': 'array',
    'location': 'xml',
    'sentAs': 'Rule',
    'items': {
      'type': 'object',
      'parameters': {
        'ID': {
          'sentAs': 'ID'
        },
        'Prefix': {
          'sentAs': 'Prefix'
        },
        'Status': {
          'sentAs': 'Status'
        },
        'Destination': {
          'type': 'object',
          'sentAs': 'Destination',
          'parameters': {
            'Bucket': {
              'sentAs': 'Bucket',
              'type': 'adapter'
            },
            'StorageClass': {
              'sentAs': 'StorageClass',
              'type': 'adapter'
            }
          }
        },
        'HistoricalObjectReplication': {
          'sentAs': 'HistoricalObjectReplication'
        }
      }
    }
  }
  var CDNNotifyConfiguration = {
    'location': 'xml',
    'sentAs': 'Domain',
    'type': 'array',
    'items': {
      'type': 'object',
      'parameters': {
        'Name': {
          'type': 'string',
          'sentAs': 'Name'
        },
        'Event': {
          'type': 'array',
          'items': {
            'type': 'adapter'
          },
          'sentAs': 'Event'

        }
      }
    }
  }

  var operations = {

    'HeadBucket': {
      'httpMethod': 'HEAD',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'HeadApiVersion': {
      'httpMethod': 'HEAD',
      'urlPath': 'apiversion',
      'parameters': {
        'Bucket': {
          'location': 'uri'
        }
      }
    },

    'HeadApiVersionOutput': {
      'parameters': {
        'ApiVersion': {
          'location': 'header',
          'sentAs': 'x-obs-api'
        }
      }
    },

    'CreateBucket': {
      'httpMethod': 'PUT',
      'data': {
        'xmlRoot': 'CreateBucketConfiguration'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ACL': {
          'location': 'header',
          'sentAs': 'acl',
          'withPrefix': true
        },
        'StorageType': {
          'location': 'header',
          'sentAs': 'x-default-storage-class'
        },
        'FileInterface': {
          'location': 'header',
          'sentAs': 'fs-file-interface',
          'withPrefix': true
        },
        'Type': {
          'location': 'header',
          'sentAs': 'bucket-type',
          'withPrefix': true
        },
        'MultiAz': {
          'location': 'header',
          'sentAs': 'x-obs-az-redundancy'
        },
        'Cluster': {
          'location': 'header',
          'sentAs': 'location-clustergroup-id',
          'withPrefix': true
        },
        'GrantFullControl': {
          'location': 'header',
          'sentAs': 'grant-full-control',
          'withPrefix': true
        },
        'GrantRead': {
          'location': 'header',
          'sentAs': 'grant-read',
          'withPrefix': true
        },
        'GrantReadACP': {
          'location': 'header',
          'sentAs': 'grant-read-acp',
          'withPrefix': true
        },
        'GrantWrite': {
          'location': 'header',
          'sentAs': 'grant-write',
          'withPrefix': true
        },
        'GrantWriteACP': {
          'location': 'header',
          'sentAs': 'grant-write-acp',
          'withPrefix': true
        },
        'ClusterType': {
          'location': 'header',
          'sentAs': 'cluster-type',
          'withPrefix': true
        },
        'MultiEnterprise': { 'location': 'header', 'sentAs': 'epid', 'withPrefix': true },
        'Location': {
          'location': 'xml',
          'sentAs': 'LocationConstraint'
        }
      }
    },

    'GetBucketMetadata': {
      'httpMethod': 'HEAD',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Origin': {
          'location': 'header',
          'sentAs': 'Origin'
        },

        'RequestHeader': {
          'location': 'header',
          'sentAs': 'Access-Control-Request-Headers'
        }
      }
    },

    'GetBucketMetadataOutput': {
      'parameters': {
        'StorageClass': {
          'location': 'header',
          'sentAs': 'x-default-storage-class'
        },
        'ObsVersion': {
          'location': 'header',
          'sentAs': 'x-obs-version'
        },
        'Location': {
          'location': 'header',
          'sentAs': 'bucket-region',
          'withPrefix': true
        },
        'FileInterface': {
          'location': 'header',
          'sentAs': 'fs-file-interface',
          'withPrefix': true
        },
        'Type': {
          'location': 'header',
          'sentAs': 'bucket-type',
          'withPrefix': true
        },
        'MultiAz': {
          'location': 'header',
          'sentAs': 'x-obs-az-redundancy'
        },
        'MultiEnterprise': {
          'location': 'header',
          'sentAs': 'epid',
          'withPrefix': true
        },
        'ClusterType': {
          'location': 'header',
          'sentAs': 'cluster-type',
          'withPrefix': true
        },
        'Cluster': {
          'location': 'header',
          'sentAs': 'location-clustergroup-id',
          'withPrefix': true
        },
        'AllowOrigin': {
          'location': 'header',
          'sentAs': 'access-control-allow-origin'
        },
        'MaxAgeSeconds': {
          'location': 'header',
          'sentAs': 'access-control-max-age'
        },
        'ExposeHeader': {
          'location': 'header',
          'sentAs': 'access-control-expose-headers'
        },
        'AllowMethod': {
          'location': 'header',
          'sentAs': 'access-control-allow-methods'
        },
        'AllowHeader': {
          'location': 'header',
          'sentAs': 'access-control-allow-headers'
        }
      }
    },

    'DeleteBucket': {
      'httpMethod': 'DELETE',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'ListBuckets': {
      'httpMethod': 'GET',
      'parameters': {
        'Type': {
          'sentAs': 'x-obs-bucket-type',
          'location': 'header'
        },
        'Location': {
          'sentAs': 'location',
          'location': 'header',
          'withPrefix': true
        }
      }
    },
    'ListBucketsOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ListAllMyBucketsResult'
      },
      'parameters': {
        Buckets: {
          location: 'xml',
          sentAs: 'Bucket',
          type: 'array',
          wrapper: 'Buckets',
          items: {
            type: 'object',
            location: 'xml',
            sentAs: 'Bucket',
            parameters: {
              Name: {
                sentAs: 'Name'
              },
              CreationDate: {
                sentAs: 'CreationDate'
              },
              Location: {
                sentAs: 'Location'
              },
              ClusterType: {
                sentAs: 'ClusterType'
              }
            }
          }
        },
        'Owner': {
          'type': 'object',
          'location': 'xml',
          'sentAs': 'Owner',
          'parameters': {
            'ID': {
              'sentAs': 'ID'
            },
            'DisplayName': {
              'sentAs': 'DisplayName'
            }
          }
        }
      }
    },

    'ListObjects': {
      'httpMethod': 'GET',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Prefix': {
          'location': 'urlPath',
          'sentAs': 'prefix'
        },
        'Marker': {
          'location': 'urlPath',
          'sentAs': 'marker'
        },
        'MaxKeys': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'max-keys'
        },
        'Delimiter': {
          'location': 'urlPath',
          'sentAs': 'delimiter'
        },
        'EncodingType': {
          'location': 'urlPath',
          'sentAs': 'encoding-type'
        }
      }
    },

    'ListObjectsOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ListBucketResult'
      },
      'parameters': {
        'Location': {
          'location': 'header',
          'sentAs': 'bucket-region',
          'withPrefix': true
        },
        'Bucket': {
          'location': 'xml',
          'sentAs': 'Name'
        },
        'Delimiter': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Delimiter'
        },
        'IsTruncated': {
          'location': 'xml',
          'sentAs': 'IsTruncated'
        },
        'Prefix': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Prefix'
        },
        'Marker': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Marker'
        },
        'NextMarker': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'NextMarker'
        },
        'MaxKeys': {
          'location': 'xml',
          'sentAs': 'MaxKeys'
        },
        'EncodingType': {
          'location': 'xml',
          'sentAs': 'EncodingType'
        },
        'Contents': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Contents',
          'items': {
            'type': 'object',
            'parameters': {
              'Key': {
                'decode': true,
                'sentAs': 'Key'
              },
              'LastModified': {
                'sentAs': 'LastModified'
              },
              'ETag': {
                'sentAs': 'ETag'
              },
              'Size': {
                'sentAs': 'Size'
              },
              'Type': {
                'sentAs': 'Type'
              },
              'StorageClass': {
                'sentAs': 'StorageClass'
              },
              'Owner': owner
            }
          }

        },
        'CommonPrefixes': commonPrefixes
      }
    },

    'ListVersions': {
      'httpMethod': 'GET',
      'urlPath': 'versions',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Prefix': {
          'location': 'urlPath',
          'sentAs': 'prefix'
        },
        'KeyMarker': {
          'location': 'urlPath',
          'sentAs': 'key-marker'
        },
        'MaxKeys': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'max-keys'
        },
        'Delimiter': {
          'location': 'urlPath',
          'sentAs': 'delimiter'
        },
        'VersionIdMarker': {
          'location': 'urlPath',
          'sentAs': 'version-id-marker'
        },
        'EncodingType': {
          'location': 'urlPath',
          'sentAs': 'encoding-type'
        }
      }
    },
    'ListVersionsOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ListVersionsResult'
      },
      'parameters': {
        'EncodingType': {
          'location': 'xml',
          'sentAs': 'EncodingType'
        },
        'Location': {
          'location': 'header',
          'sentAs': 'bucket-region',
          'withPrefix': true
        },
        'Bucket': {
          'location': 'xml',
          'sentAs': 'Name'
        },
        'Prefix': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Prefix'
        },
        'Delimiter': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Delimiter'
        },
        'KeyMarker': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'KeyMarker'
        },
        'VersionIdMarker': {
          'location': 'xml',
          'sentAs': 'VersionIdMarker'
        },
        'NextKeyMarker': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'NextKeyMarker'
        },
        'NextVersionIdMarker': {
          'location': 'xml',
          'sentAs': 'NextVersionIdMarker'
        },
        'MaxKeys': {
          'location': 'xml',
          'sentAs': 'MaxKeys'
        },
        'IsTruncated': {
          'location': 'xml',
          'sentAs': 'IsTruncated'
        },
        'Versions': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Version',
          'items': {
            'type': 'object',
            'parameters': {
              'Key': {
                'decode': true,
                'sentAs': 'Key'
              },
              'VersionId': {
                'sentAs': 'VersionId'
              },
              'IsLatest': {
                'sentAs': 'IsLatest'
              },
              'LastModified': {
                'sentAs': 'LastModified'
              },
              'ETag': {
                'sentAs': 'ETag'
              },
              'Size': {
                'sentAs': 'Size'
              },
              'Type': {
                'sentAs': 'Type'
              },
              'Owner': owner,
              'StorageClass': {
                'sentAs': 'StorageClass'
              }
            }
          }
        },
        'DeleteMarkers': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'DeleteMarker',
          'items': {
            'type': 'object',
            'parameters': {
              'Key': {
                'decode': true,
                'sentAs': 'Key'
              },
              'VersionId': {
                'sentAs': 'VersionId'
              },
              'IsLatest': {
                'sentAs': 'IsLatest'
              },
              'LastModified': {
                'sentAs': 'LastModified'
              },
              'Owner': owner
            }
          }
        },
        'CommonPrefixes': commonPrefixes
      }
    },

    'PutBackToSource': {
      'httpMethod': 'PUT',
      'data': {
        'xmlRoot': 'BackToSourceConfiguration'
      },
      'urlPath': 'backtosource',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'BackToSourceRules': BackToSourceRules,
        'ContentMD5': {
          'location': 'header',
          'sentAs': 'Content-MD5'
        }
      }
    },

    'DeleteBackToSource': {
      'httpMethod': 'DELETE',
      'urlPath': 'backtosource',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBackToSource': {
      'httpMethod': 'GET',
      'urlPath': 'backtosource',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBackToSourceOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'BackToSourceConfiguration'
      },
      'parameters': {
        'BackToSourceRules': BackToSourceRules
      }
    },

    'GetBucketLocation': {
      'httpMethod': 'GET',
      'urlPath': 'location',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketLocationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'CreateBucketConfiguration'
      },
      'parameters': {
        'Location': {
          'location': 'xml',
          'sentAs': 'LocationConstraint'
        }
      }
    },

    'GetBucketStorageInfo': {
      'httpMethod': 'GET',
      'urlPath': 'storageinfo',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketStorageInfoOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'GetBucketStorageInfoResult'
      },
      'parameters': {
        'Size': {
          'location': 'xml',
          'sentAs': 'Size'
        },
        'ObjectNumber': {
          'location': 'xml',
          'sentAs': 'ObjectNumber'
        }
      }
    },

    'SetBucketQuota': {
      'httpMethod': 'PUT',
      'urlPath': 'quota',
      'data': {
        'xmlRoot': 'Quota'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'StorageQuota': {
          'required': true,
          'location': 'xml',
          'sentAs': 'StorageQuota'
        }
      }
    },

    'GetBucketQuota': {
      'httpMethod': 'GET',
      'urlPath': 'quota',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }

      }
    },
    'GetBucketQuotaOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'Quota'
      },
      'parameters': {
        'StorageQuota': {
          'location': 'xml',
          'sentAs': 'StorageQuota'
        }
      }
    },

    'SetBucketAcl': {
      'httpMethod': 'PUT',
      'urlPath': 'acl',
      'data': {
        'xmlRoot': 'AccessControlPolicy'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ACL': {
          'location': 'header',
          'sentAs': 'acl',
          'withPrefix': true,
          'type': 'adapter'
        },
        'Owner': owner,
        'Grants': grants
      }
    },

    'GetBucketAcl': {
      'httpMethod': 'GET',
      'urlPath': 'acl',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketAclOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'AccessControlPolicy'
      },
      'parameters': {
        'Owner': owner,
        'Grants': grants
      }
    },

    'SetBucketLoggingConfiguration': {
      'httpMethod': 'PUT',
      'urlPath': 'logging',
      'data': {
        'xmlRoot': 'BucketLoggingStatus',
        'xmlAllowEmpty': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'LoggingEnabled': loggingEnabled
      }
    },

    'GetBucketLoggingConfiguration': {
      'httpMethod': 'GET',
      'urlPath': 'logging',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketLoggingConfigurationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'BucketLoggingStatus'
      },
      'parameters': {
        'LoggingEnabled': loggingEnabled
      }
    },

    'SetBucketPolicy': {
      'httpMethod': 'PUT',
      'urlPath': 'policy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Policy': {
          'required': true,
          'location': 'body'
        }
      }
    },

    'SetSFSAcl': {
      'httpMethod': 'PUT',
      'urlPath': 'sfsacl',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Policy': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'GetSFSAcl': {
      'httpMethod': 'GET',
      'urlPath': 'sfsacl',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetSFSAclOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'Policy': {
          'location': 'body'
        }
      }
    },
    'DeleteSFSAcl': {
      'httpMethod': 'DELETE',
      'urlPath': 'sfsacl',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketPolicy': {
      'httpMethod': 'GET',
      'urlPath': 'policy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketPolicyOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'Policy': {
          'location': 'body'
        }
      }
    },

    'DeleteBucketPolicy': {
      'httpMethod': 'DELETE',
      'urlPath': 'policy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'SetBucketDisPolicy': {
      'httpMethod': 'PUT',
      'urlPath': 'disPolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        },
        'Rules': {
          'required': true,
          'location': 'body'
        }
      }
    },

    'GetBucketDisPolicy': {
      'httpMethod': 'GET',
      'urlPath': 'disPolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        }
      }
    },

    'GetBucketDisPolicyOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'Rules': {
          'location': 'body'
        }
      }
    },

    'DeleteBucketDisPolicy': {
      'httpMethod': 'DELETE',
      'urlPath': 'disPolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        }
      }
    },

    'SetBucketLifecycleConfiguration': {
      'httpMethod': 'PUT',
      'urlPath': 'lifecycle',
      'data': {
        'xmlRoot': 'LifecycleConfiguration',
        'md5': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Rules': rules
      }
    },

    'GetBucketLifecycleConfiguration': {
      'httpMethod': 'GET',
      'urlPath': 'lifecycle',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketLifecycleConfigurationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'LifecycleConfiguration'
      },
      'parameters': {
        'Rules': rules
      }
    },
    'DeleteBucketLifecycleConfiguration': {
      'httpMethod': 'DELETE',
      'urlPath': 'lifecycle',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'SetBucketWebsiteConfiguration': {
      'httpMethod': 'PUT',
      'urlPath': 'website',
      'data': {
        'xmlRoot': 'WebsiteConfiguration'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'RedirectAllRequestsTo': redirectAllRequestsTo,
        'IndexDocument': indexDocument,
        'ErrorDocument': errorDocument,
        'RoutingRules': routingRules
      }
    },

    'GetBucketWebsiteConfiguration': {
      'httpMethod': 'GET',
      'urlPath': 'website',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketWebsiteConfigurationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'WebsiteConfiguration'
      },
      'parameters': {
        'RedirectAllRequestsTo': redirectAllRequestsTo,
        'IndexDocument': indexDocument,
        'ErrorDocument': errorDocument,
        'RoutingRules': routingRules
      }
    },

    'DeleteBucketWebsiteConfiguration': {
      'httpMethod': 'DELETE',
      'urlPath': 'website',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'SetBucketVersioningConfiguration': {
      'httpMethod': 'PUT',
      'urlPath': 'versioning',
      'data': {
        'xmlRoot': 'VersioningConfiguration'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'VersionStatus': {
          'required': true,
          'location': 'xml',
          'sentAs': 'Status'
        }
      }
    },

    'GetBucketVersioningConfiguration': {
      'httpMethod': 'GET',
      'urlPath': 'versioning',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketVersioningConfigurationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'VersioningConfiguration'
      },
      'parameters': {
        'VersionStatus': {
          'location': 'xml',
          'sentAs': 'Status'
        }
      }
    },

    'SetBucketCors': {
      'httpMethod': 'PUT',
      'urlPath': 'cors',
      'data': {
        'xmlRoot': 'CORSConfiguration',
        'md5': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'CorsRules': corsRule
      }
    },

    'GetBucketCors': {
      'httpMethod': 'GET',
      'urlPath': 'cors',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketCorsOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'CORSConfiguration'
      },
      'parameters': {
        'CorsRules': corsRule
      }
    },

    'DeleteBucketCors': {
      'httpMethod': 'DELETE',
      'urlPath': 'cors',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'SetBucketNotification': {
      'httpMethod': 'PUT',
      'urlPath': 'notification',
      'data': {
        'xmlRoot': 'NotificationConfiguration',
        'xmlAllowEmpty': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'TopicConfigurations': topicConfiguration,
        'FunctionGraphConfigurations': functionGraphConfiguration,
        'FunctionStageConfigurations': functionStageConfiguration
      }
    },

    'GetBucketNotification': {
      'httpMethod': 'GET',
      'urlPath': 'notification',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketNotificationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'NotificationConfiguration'
      },
      'parameters': {
        'TopicConfigurations': topicConfiguration,
        'FunctionGraphConfigurations': functionGraphConfiguration,
        'FunctionStageConfigurations': functionStageConfiguration
      }
    },

    'SetBucketTagging': {
      'httpMethod': 'PUT',
      'urlPath': 'tagging',
      'data': {
        'xmlRoot': 'Tagging',
        'md5': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Tags': tagSet
      }
    },

    'DeleteBucketTagging': {
      'httpMethod': 'DELETE',
      'urlPath': 'tagging',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketTagging': {
      'httpMethod': 'GET',
      'urlPath': 'tagging',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketTaggingOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'Tagging'
      },
      'parameters': {
        'Tags': tagSet
      }
    },

    'SetBucketStoragePolicy': {
      'httpMethod': 'PUT',
      'urlPath': 'storagePolicy',
      'data': {
        'xmlRoot': 'StoragePolicy'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'StorageClass': {
          'required': true,
          'location': 'xml',
          'type': 'adapter',
          'sentAs': 'DefaultStorageClass'
        }
      }
    },

    'GetBucketStoragePolicy': {
      'httpMethod': 'GET',
      'urlPath': 'storagePolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketStoragePolicyOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'StoragePolicy'
      },
      'parameters': {
        'StorageClass': {
          'location': 'xml',
          'type': 'string',
          'sentAs': 'DefaultStorageClass'
        }
      }
    },

    'SetBucketReplication': {
      'httpMethod': 'PUT',
      'urlPath': 'replication',
      'data': {
        'xmlRoot': 'ReplicationConfiguration',
        'md5': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Agency': {
          'location': 'xml',
          'sentAs': 'Agency'
        },
        'Rules': replicationRules
      }
    },

    'GetBucketReplication': {
      'httpMethod': 'GET',
      'urlPath': 'replication',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketReplicationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ReplicationConfiguration'
      },
      'parameters': {
        'Agency': {
          'location': 'xml',
          'sentAs': 'Agency'
        },
        'Rules': replicationRules
      }
    },

    'DeleteBucketReplication': {
      'httpMethod': 'DELETE',
      'urlPath': 'replication',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'PutObject': {
      'httpMethod': 'PUT',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'ContentMD5': {
          'location': 'header',
          'sentAs': 'Content-MD5'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'Offset': {
          'type': 'plain'
        },
        'ContentLength': {
          'location': 'header',
          'sentAs': 'Content-Length',
          'type': 'plain'
        },
        'ACL': {
          'location': 'header',
          'sentAs': 'acl',
          'withPrefix': true,
          'type': 'adapter'
        },
        'GrantRead': {
          'location': 'header',
          'sentAs': 'grant-read',
          'withPrefix': true
        },
        'GrantReadAcp': {
          'location': 'header',
          'sentAs': 'grant-read-acp',
          'withPrefix': true
        },
        'GrantWriteAcp': {
          'location': 'header',
          'sentAs': 'grant-write-acp',
          'withPrefix': true
        },
        'GrantFullControl': {
          'location': 'header',
          'sentAs': 'grant-full-control',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true,
          'type': 'adapter'
        },
        'Metadata': {
          'type': 'object',
          'location': 'header',
          'sentAs': 'meta-',
          'withPrefix': true
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        },
        'Expires': {
          'location': 'header',
          'sentAs': 'x-obs-expires',
          'type': 'number'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true,
          'type': 'adapter'
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-aws-kms-key-id',
          'withPrefix': true
        },
        'SseKmsProjectId': {
          'location': 'header',
          'sentAs': 'sse-kms-key-project-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        },
        'Body': {
          'location': 'body'
        },
        'SourceFile': {
          'type': 'srcFile'
        },
        'ProgressCallback': {
          'type': 'plain'
        }
      }
    },
    'PutObjectOutput': {
      'parameters': {
        'ETag': {
          'location': 'header',
          'sentAs': 'etag'
        },
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-aws-kms-key-id',
          'withPrefix': true
        },
        'SseKmsProjectId': {
          'location': 'header',
          'sentAs': 'sse-kms-key-project-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        }
      }
    },

    'AppendObject': {
      'httpMethod': 'POST',
      'urlPath': 'append',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'Position': {
          'location': 'urlPath',
          'sentAs': 'position',
          'type': 'number'
        },
        'ContentMD5': {
          'location': 'header',
          'sentAs': 'Content-MD5'
        },
        'Offset': {
          'type': 'plain'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'ContentLength': {
          'location': 'header',
          'sentAs': 'Content-Length',
          'type': 'plain'
        },
        'ACL': {
          'location': 'header',
          'sentAs': 'acl',
          'withPrefix': true,
          'type': 'adapter'
        },
        'GrantRead': {
          'location': 'header',
          'sentAs': 'grant-read',
          'withPrefix': true
        },
        'GrantReadAcp': {
          'location': 'header',
          'sentAs': 'grant-read-acp',
          'withPrefix': true
        },
        'GrantWriteAcp': {
          'location': 'header',
          'sentAs': 'grant-write-acp',
          'withPrefix': true
        },
        'GrantFullControl': {
          'location': 'header',
          'sentAs': 'grant-full-control',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true,
          'type': 'adapter'
        },
        'Metadata': {
          'type': 'object',
          'location': 'header',
          'sentAs': 'meta-',
          'withPrefix': true
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        },
        'Expires': {
          'location': 'header',
          'sentAs': 'x-obs-expires',
          'type': 'number'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true,
          'type': 'adapter'
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        },
        'Body': {
          'location': 'body'
        },
        'SourceFile': {
          'type': 'srcFile'
        },
        'ProgressCallback': {
          'type': 'plain'
        }
      }
    },
    'AppendObjectOutput': {
      'parameters': {
        'ETag': {
          'location': 'header',
          'sentAs': 'etag'
        },
        'NextPosition': {
          'location': 'header',
          'sentAs': 'x-obs-next-append-position'
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        }
      }
    },

    'GetObject': {
      'httpMethod': 'GET',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'ResponseCacheControl': {
          'location': 'urlPath',
          'sentAs': 'response-cache-control'
        },
        'ResponseContentDisposition': {
          'location': 'urlPath',
          'sentAs': 'response-content-disposition'
        },
        'ResponseContentEncoding': {
          'location': 'urlPath',
          'sentAs': 'response-content-encoding'
        },
        'ResponseContentLanguage': {
          'location': 'urlPath',
          'sentAs': 'response-content-language'
        },
        'ResponseContentType': {
          'location': 'urlPath',
          'sentAs': 'response-content-type'
        },
        'ResponseExpires': {
          'location': 'urlPath',
          'sentAs': 'response-expires'
        },
        'VersionId': {
          'location': 'urlPath',
          'sentAs': 'versionId'
        },
        'ImageProcess': {
          'location': 'urlPath',
          'sentAs': 'x-image-process'
        },
        'IfMatch': {
          'location': 'header',
          'sentAs': 'If-Match'
        },
        'IfModifiedSince': {
          'location': 'header',
          'sentAs': 'If-Modified-Since'
        },
        'IfNoneMatch': {
          'location': 'header',
          'sentAs': 'If-None-Match'
        },
        'IfUnmodifiedSince': {
          'location': 'header',
          'sentAs': 'If-Unmodified-Since'
        },
        'Range': {
          'location': 'header',
          'sentAs': 'Range'
        },
        'Origin': {
          'location': 'header',
          'sentAs': 'Origin'
        },
        'RequestHeader': {
          'location': 'header',
          'sentAs': 'Access-Control-Request-Headers'
        },
        'SaveByType': {
          'type': 'dstFile'
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        },
        'ProgressCallback': {
          'type': 'plain'
        }
      }
    },
    'GetObjectOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'Content': {
          'location': 'body'
        },
        'Expiration': {
          'location': 'header',
          'sentAs': 'expiration',
          'withPrefix': true
        },
        'ETag': {
          'location': 'header',
          'sentAs': 'etag'
        },
        'CacheControl': {
          'location': 'header',
          'sentAs': 'Cache-Control'
        },
        'ContentDisposition': {
          'location': 'header',
          'sentAs': 'Content-Disposition'
        },
        'ContentEncoding': {
          'location': 'header',
          'sentAs': 'Content-Encoding'
        },
        'ContentLanguage': {
          'location': 'header',
          'sentAs': 'Content-Language'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'Expires': {
          'location': 'header',
          'sentAs': 'Expires'
        },
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        },
        'ContentLength': {
          'location': 'header',
          'sentAs': 'Content-Length'
        },
        'DeleteMarker': {
          'location': 'header',
          'sentAs': 'delete-marker',
          'withPrefix': true
        },
        'LastModified': {
          'location': 'header',
          'sentAs': 'Last-Modified'
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true
        },
        'Restore': {
          'location': 'header',
          'sentAs': 'restore',
          'withPrefix': true
        },
        'AllowOrigin': {
          'location': 'header',
          'sentAs': 'access-control-allow-origin'
        },
        'MaxAgeSeconds': {
          'location': 'header',
          'sentAs': 'access-control-max-age'
        },
        'ExposeHeader': {
          'location': 'header',
          'sentAs': 'access-control-expose-headers'
        },
        'AllowMethod': {
          'location': 'header',
          'sentAs': 'access-control-allow-methods'
        },
        'AllowHeader': {
          'location': 'header',
          'sentAs': 'access-control-allow-headers'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-aws-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        },
        'Metadata': {
          'location': 'header',
          'type': 'object',
          'sentAs': 'meta-',
          'withPrefix': true
        }
      }
    },

    'CopyObject': {
      'httpMethod': 'PUT',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'ACL': {
          'location': 'header',
          'sentAs': 'acl',
          'withPrefix': true,
          'type': 'adapter'
        },
        'GrantRead': {
          'location': 'header',
          'sentAs': 'grant-read',
          'withPrefix': true
        },
        'GrantReadAcp': {
          'location': 'header',
          'sentAs': 'grant-read-acp',
          'withPrefix': true
        },

        'GrantWriteAcp': {
          'location': 'header',
          'sentAs': 'grant-write-acp',
          'withPrefix': true
        },
        'GrantFullControl': {
          'location': 'header',
          'sentAs': 'grant-full-control',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true,
          'type': 'adapter'
        },
        'CopySource': {
          'required': true,
          'location': 'header',
          'sentAs': 'copy-source',
          'withPrefix': true,
          'skipEncoding': true
        },
        'CopySourceIfMatch': {
          'location': 'header',
          'sentAs': 'copy-source-if-match',
          'withPrefix': true
        },
        'CopySourceIfModifiedSince': {
          'location': 'header',
          'sentAs': 'copy-source-if-modified-since',
          'withPrefix': true
        },
        'CopySourceIfNoneMatch': {
          'location': 'header',
          'sentAs': 'copy-source-if-none-match',
          'withPrefix': true
        },
        'CopySourceIfUnmodifiedSince': {
          'location': 'header',
          'sentAs': 'copy-source-if-unmodified-since',
          'withPrefix': true
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'ContentEncoding': {
          'location': 'header',
          'sentAs': 'content-encoding'
        },
        'ContentLanguage': {
          'location': 'header',
          'sentAs': 'content-language'
        },
        'ContentDisposition': {
          'location': 'header',
          'sentAs': 'content-disposition'
        },
        'CacheControl': {
          'location': 'header',
          'sentAs': 'cache-control'
        },
        'Expires': {
          'location': 'header',
          'sentAs': 'expires'
        },
        'Metadata': {
          'type': 'object',
          'location': 'header',
          'sentAs': 'meta-',
          'withPrefix': true
        },
        'MetadataDirective': {
          'location': 'header',
          'sentAs': 'metadata-directive',
          'withPrefix': true
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true,
          'type': 'adapter'
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-aws-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        },
        'CopySourceSseC': {
          'location': 'header',
          'sentAs': 'copy-source-server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'CopySourceSseCKey': {
          'location': 'header',
          'sentAs': 'copy-source-server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        }
      }
    },
    'CopyObjectOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'CopyObjectResult'
      },
      'parameters': {
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        },
        'CopySourceVersionId': {
          'location': 'header',
          'sentAs': 'copy-source-version-id',
          'withPrefix': true
        },
        'ETag': {
          'location': 'xml',
          'sentAs': 'ETag'
        },
        'LastModified': {
          'location': 'xml',
          'sentAs': 'LastModified'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-aws-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        }
      }
    },

    'RestoreObject': {
      'httpMethod': 'POST',
      'urlPath': 'restore',
      'data': {
        'xmlRoot': 'RestoreRequest',
        'md5': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'VersionId': {
          'location': 'urlPath',
          'sentAs': 'versionId'
        },
        'Days': {
          'location': 'xml',
          'sentAs': 'Days'
        },
        'Tier': {
          'wrapper': 'GlacierJobParameters',
          'location': 'xml',
          'sentAs': 'Tier'
        }
      }
    },

    'GetObjectMetadata': {
      'httpMethod': 'HEAD',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'VersionId': {
          'location': 'urlPath',
          'sentAs': 'versionId'
        },
        'Origin': {
          'location': 'header',
          'sentAs': 'Origin'
        },
        'RequestHeader': {
          'location': 'header',
          'sentAs': 'Access-Control-Request-Headers'
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        }
      }
    },
    'GetObjectMetadataOutput': {
      'parameters': {
        'Expiration': {
          'location': 'header',
          'sentAs': 'expiration',
          'withPrefix': true
        },
        'LastModified': {
          'location': 'header',
          'sentAs': 'Last-Modified'
        },
        'ContentLength': {
          'location': 'header',
          'sentAs': 'Content-Length'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'ETag': {
          'location': 'header',
          'sentAs': 'etag'
        },
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true
        },
        'Restore': {
          'location': 'header',
          'sentAs': 'restore',
          'withPrefix': true
        },
        'ObjectType': {
          'location': 'header',
          'sentAs': 'x-obs-object-type'
        },
        'NextPosition': {
          'location': 'header',
          'sentAs': 'x-obs-next-append-position'
        },

        'AllowOrigin': {
          'location': 'header',
          'sentAs': 'access-control-allow-origin'
        },
        'MaxAgeSeconds': {
          'location': 'header',
          'sentAs': 'access-control-max-age'
        },
        'ExposeHeader': {
          'location': 'header',
          'sentAs': 'access-control-expose-headers'
        },
        'AllowMethod': {
          'location': 'header',
          'sentAs': 'access-control-allow-methods'
        },
        'AllowHeader': {
          'location': 'header',
          'sentAs': 'access-control-allow-headers'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-aws-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        },
        'Metadata': {
          'location': 'header',
          'type': 'object',
          'sentAs': 'meta-',
          'withPrefix': true
        },
        'ContentLanguage': {
          'location': 'header',
          'sentAs': 'Content-Language'
        },
        'ContentEncoding': {
          'location': 'header',
          'sentAs': 'Content-Encoding'
        },
        'CacheControl': {
          'location': 'header',
          'sentAs': 'Cache-Control'
        },
        'ContentDisposition': {
          'location': 'header',
          'sentAs': 'Content-Disposition'
        },
        'Expires': {
          'location': 'header',
          'sentAs': 'Expires'
        },
        'ReplicationStatus': {
          'location': 'header',
          'sentAs': 'replication-status',
          'withPrefix': true
        }
      }
    },

    'SetObjectMetadata': {
      'httpMethod': 'PUT',
      'urlPath': 'metadata',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'VersionId': {
          'location': 'urlPath',
          'sentAs': 'versionId'
        },
        'Origin': {
          'location': 'header',
          'sentAs': 'Origin'
        },
        'RequestHeader': {
          'location': 'header',
          'sentAs': 'Access-Control-Request-Headers'
        },
        'CacheControl': {
          'location': 'header',
          'sentAs': 'Cache-Control'
        },
        'ContentDisposition': {
          'location': 'header',
          'sentAs': 'Content-Disposition'
        },
        'ContentLanguage': {
          'location': 'header',
          'sentAs': 'Content-Language'
        },
        'ContentEncoding': {
          'location': 'header',
          'sentAs': 'Content-Encoding'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'Expires': {
          'location': 'header',
          'sentAs': 'Expires'
        },
        'Metadata': {
          'shape': 'Sy',
          'location': 'header',
          'type': 'object',
          'sentAs': 'meta-',
          'withPrefix': true
        },
        'MetadataDirective': {
          'location': 'header',
          'sentAs': 'metadata-directive',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        }
      }
    },
    'SetObjectMetadataOutput': {
      'parameters': {
        'Expires': {
          'location': 'header',
          'sentAs': 'Expires'
        },
        'ContentLength': {
          'location': 'header',
          'sentAs': 'Content-Length'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'ContentLanguage': {
          'location': 'header',
          'sentAs': 'Content-Language'
        },
        'CacheControl': {
          'location': 'header',
          'sentAs': 'Cache-Control'
        },
        'ContentDisposition': {
          'location': 'header',
          'sentAs': 'Content-Disposition'
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true,
          'type': 'adapter'
        },
        'Metadata': {
          'location': 'header',
          'type': 'object',
          'sentAs': 'meta-',
          'withPrefix': true
        }
      }
    },

    'SetObjectAcl': {
      'httpMethod': 'PUT',
      'urlPath': 'acl',
      'data': {
        'xmlRoot': 'AccessControlPolicy'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'VersionId': {
          'location': 'urlPath',
          'sentAs': 'versionId'
        },
        'ACL': {
          'location': 'header',
          'sentAs': 'acl',
          'withPrefix': true,
          'type': 'adapter'
        },
        'Owner': owner,
        'Grants': grants
      }
    },
    'SetObjectAclOutput': {
      'parameters': {
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        }
      }
    },
    'GetObjectAcl': {
      'httpMethod': 'GET',
      'urlPath': 'acl',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'VersionId': {
          'location': 'urlPath',
          'sentAs': 'versionId'
        }
      }
    },
    'GetObjectAclOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'AccessControlPolicy'
      },
      'parameters': {
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        },
        'Owner': owner,
        'Grants': grants
      }
    },
    'DeleteObject': {
      'httpMethod': 'DELETE',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'VersionId': {
          'location': 'urlPath',
          'sentAs': 'versionId'
        }
      }
    },
    'DeleteObjectOutput': {
      'parameters': {
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        },
        'DeleteMarker': {
          'location': 'header',
          'sentAs': 'delete-marker',
          'withPrefix': true
        }
      }
    },
    'DeleteObjects': {
      'httpMethod': 'POST',
      'urlPath': 'delete',
      'data': {
        'xmlRoot': 'Delete',
        'md5': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Quiet': {
          'location': 'xml',
          'sentAs': 'Quiet'
        },
        'EncodingType': {
          'location': 'xml',
          'sentAs': 'EncodingType'
        },
        'Objects': {
          'required': true,
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Object',
          'items': {
            'type': 'object',
            'parameters': {
              'Key': {
                'sentAs': 'Key'
              },
              'VersionId': {
                'sentAs': 'VersionId'
              }
            }
          }
        }
      }
    },
    'DeleteObjectsOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'DeleteResult'
      },
      'parameters': {
        'EncodingType': {
          'location': 'xml',
          'sentAs': 'EncodingType'
        },
        'Deleteds': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Deleted',
          'items': {
            'type': 'object',
            'parameters': {
              'Key': {
                'decode': true,
                'sentAs': 'Key'
              },
              'VersionId': {
                'sentAs': 'VersionId'
              },
              'DeleteMarker': {
                'sentAs': 'DeleteMarker'
              },
              'DeleteMarkerVersionId': {
                'sentAs': 'DeleteMarkerVersionId'
              }
            }
          }
        },
        'Errors': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Error',
          'items': {
            'type': 'object',
            'parameters': {
              'Key': {
                'decode': true,
                'sentAs': 'Key'
              },
              'VersionId': {
                'sentAs': 'VersionId'
              },
              'Code': {
                'sentAs': 'Code'
              },
              'Message': {
                'sentAs': 'Message'
              }
            }
          }
        }
      }
    },
    'InitiateMultipartUpload': {
      'httpMethod': 'POST',
      'urlPath': 'uploads',
      'parameters': {
        'EncodingType': {
          'location': 'urlPath',
          'sentAs': 'encoding-type'
        },
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'ACL': {
          'location': 'header',
          'sentAs': 'acl',
          'withPrefix': true,
          'type': 'adapter'
        },
        'GrantRead': {
          'location': 'header',
          'sentAs': 'grant-read',
          'withPrefix': true
        },
        'GrantReadAcp': {
          'location': 'header',
          'sentAs': 'grant-read-acp',
          'withPrefix': true
        },
        'GrantWriteAcp': {
          'location': 'header',
          'sentAs': 'grant-write-acp',
          'withPrefix': true
        },
        'GrantFullControl': {
          'location': 'header',
          'sentAs': 'grant-full-control',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true,
          'type': 'adapter'
        },
        'Metadata': {
          'type': 'object',
          'location': 'header',
          'sentAs': 'meta-',
          'withPrefix': true
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        },
        'Expires': {
          'location': 'header',
          'sentAs': 'x-obs-expires',
          'type': 'number'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true,
          'type': 'adapter'
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-aws-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        }
      }
    },
    'InitiateMultipartUploadOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'InitiateMultipartUploadResult'
      },
      'parameters': {
        'EncodingType': {
          'location': 'xml',
          'sentAs': 'EncodingType'
        },
        'Bucket': {
          'location': 'xml',
          'sentAs': 'Bucket'
        },
        'Key': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Key'
        },
        'UploadId': {
          'location': 'xml',
          'sentAs': 'UploadId'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-aws-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        }
      }
    },
    'ListMultipartUploads': {
      'httpMethod': 'GET',
      'urlPath': 'uploads',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Delimiter': {
          'location': 'urlPath',
          'sentAs': 'delimiter'
        },
        'KeyMarker': {
          'location': 'urlPath',
          'sentAs': 'key-marker'
        },
        'MaxUploads': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'max-uploads'
        },
        'Prefix': {
          'location': 'urlPath',
          'sentAs': 'prefix'
        },
        'UploadIdMarker': {
          'location': 'urlPath',
          'sentAs': 'upload-id-marker'
        },
        'EncodingType': {
          'location': 'urlPath',
          'sentAs': 'encoding-type'
        }
      }
    },
    'ListMultipartUploadsOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ListMultipartUploadsResult'
      },
      'parameters': {
        'Bucket': {
          'location': 'xml',
          'sentAs': 'Bucket'
        },
        'KeyMarker': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'KeyMarker'
        },
        'UploadIdMarker': {
          'location': 'xml',
          'sentAs': 'UploadIdMarker'
        },
        'NextKeyMarker': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'NextKeyMarker'
        },
        'Prefix': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Prefix'
        },
        'Delimiter': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Delimiter'
        },
        'NextUploadIdMarker': {
          'location': 'xml',
          'sentAs': 'NextUploadIdMarker'
        },
        'MaxUploads': {
          'location': 'xml',
          'sentAs': 'MaxUploads'
        },
        'IsTruncated': {
          'location': 'xml',
          'sentAs': 'IsTruncated'
        },
        'EncodingType': {
          'location': 'xml',
          'sentAs': 'EncodingType'
        },
        'Uploads': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Upload',
          'items': {
            'type': 'object',
            'parameters': {
              'UploadId': {
                'sentAs': 'UploadId'
              },
              'Key': {
                'decode': true,
                'sentAs': 'Key'
              },
              'Initiated': {
                'sentAs': 'Initiated'
              },
              'StorageClass': {
                'sentAs': 'StorageClass'
              },
              'Owner': owner,
              'Initiator': initiator
            }
          }
        },
        'CommonPrefixes': commonPrefixes
      }
    },
    'UploadPart': {
      'httpMethod': 'PUT',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'PartNumber': {
          'required': true,
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'partNumber'
        },
        'UploadId': {
          'required': true,
          'location': 'urlPath',
          'sentAs': 'uploadId'
        },
        'ContentMD5': {
          'location': 'header',
          'sentAs': 'Content-MD5'
        },
        'Body': {
          'location': 'body'
        },
        'SourceFile': {
          'type': 'srcFile'
        },
        'Offset': {
          'type': 'plain'
        },
        'PartSize': {
          'type': 'plain'
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        },
        'ProgressCallback': {
          'type': 'plain'
        }
      }
    },
    'UploadPartOutput': {
      'parameters': {
        'ETag': {
          'location': 'header',
          'sentAs': 'etag'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-aws-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        }
      }
    },
    'ListParts': {
      'httpMethod': 'GET',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'UploadId': {
          'required': true,
          'location': 'urlPath',
          'sentAs': 'uploadId'
        },
        'MaxParts': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'max-parts'
        },
        'PartNumberMarker': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'part-number-marker'
        },
        'EncodingType': {
          'location': 'urlPath',
          'sentAs': 'encoding-type'
        }
      }
    },
    'ListPartsOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ListPartsResult'
      },
      'parameters': {
        'Bucket': {
          'location': 'xml',
          'sentAs': 'Bucket'
        },
        'Key': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Key'
        },
        'UploadId': {
          'location': 'xml',
          'sentAs': 'UploadId'
        },
        'PartNumberMarker': {
          'location': 'xml',
          'sentAs': 'PartNumberMarker'
        },
        'NextPartNumberMarker': {
          'location': 'xml',
          'sentAs': 'NextPartNumberMarker'
        },
        'MaxParts': {
          'location': 'xml',
          'sentAs': 'MaxParts'
        },
        'IsTruncated': {
          'location': 'xml',
          'sentAs': 'IsTruncated'
        },
        'StorageClass': {
          'location': 'xml',
          'sentAs': 'StorageClass'
        },
        'EncodingType': {
          'location': 'urlPath',
          'sentAs': 'EncodingType'
        },
        'Initiator': initiator,
        'Owner': owner,
        'Parts': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Part',
          'items': {
            'type': 'object',
            'parameters': {
              'PartNumber': {
                'sentAs': 'PartNumber'
              },
              'LastModified': {
                'sentAs': 'LastModified'
              },
              'ETag': {
                'sentAs': 'ETag'
              },
              'Size': {
                'sentAs': 'Size'
              }
            }
          }
        }
      }
    },
    'CopyPart': {
      'httpMethod': 'PUT',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'PartNumber': {
          'required': true,
          'location': 'urlPath',
          'sentAs': 'partNumber',
          'type': 'number'
        },
        'UploadId': {
          'required': true,
          'location': 'urlPath',
          'sentAs': 'uploadId'
        },
        'CopySource': {
          'required': true,
          'location': 'header',
          'sentAs': 'copy-source',
          'skipEncoding': true,
          'withPrefix': true
        },
        'CopySourceRange': {
          'location': 'header',
          'sentAs': 'copy-source-range',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        },
        'CopySourceSseC': {
          'location': 'header',
          'sentAs': 'copy-source-server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'CopySourceSseCKey': {
          'location': 'header',
          'sentAs': 'copy-source-server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        }
      }
    },
    'CopyPartOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'CopyPartResult'
      },
      'parameters': {
        'LastModified': {
          'location': 'xml',
          'sentAs': 'LastModified'
        },
        'ETag': {
          'location': 'xml',
          'sentAs': 'ETag'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-aws-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        }
      }
    },
    'AbortMultipartUpload': {
      'httpMethod': 'DELETE',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'UploadId': {
          'required': true,
          'location': 'urlPath',
          'sentAs': 'uploadId'
        }
      }
    },

    'CompleteMultipartUpload': {
      'httpMethod': 'POST',
      'data': {
        'xmlRoot': 'CompleteMultipartUpload'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'UploadId': {
          'required': true,
          'location': 'urlPath',
          'sentAs': 'uploadId'
        },
        'EncodingType': {
          'location': 'urlPath',
          'sentAs': 'encoding-type'
        },
        'Parts': {
          'required': true,
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Part',
          'items': {
            'type': 'object',
            'parameters': {
              'PartNumber': {
                'sentAs': 'PartNumber'
              },
              'ETag': {
                'sentAs': 'ETag'
              }
            }
          }
        }
      }
    },
    'CompleteMultipartUploadOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'CompleteMultipartUploadResult'
      },
      'parameters': {
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        },
        'Location': {
          'location': 'xml',
          'sentAs': 'Location'
        },
        'EncodingType': {
          'location': 'xml',
          'sentAs': 'EncodingType'
        },
        'Bucket': {
          'location': 'xml',
          'sentAs': 'Bucket'
        },
        'Key': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Key'
        },
        'ETag': {
          'location': 'xml',
          'sentAs': 'ETag'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-aws-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        }
      }
    },
    'GetBucketInventory': {
      'httpMethod': 'GET',
      'urlPath': 'inventory',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'

        }

      }

    },
    'GetBucketInventoryOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ListInventoryConfiguration'

      },
      'parameters': {
        'Rules': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'InventoryConfiguration',
          'items': {
            'type': 'object',
            'parameters': {
              'Id': {
                'sentAs': 'Id'

              },
              'IsEnabled': {
                'sentAs': 'IsEnabled'

              },
              'Filter': {
                'type': 'object',
                'sentAs': 'Filter',
                'parameters': {
                  'Prefix': {
                    'sentAs': 'Prefix'
                  }
                }
              },
              'Destination': {
                'type': 'object',
                'sentAs': 'Destination',
                'parameters': {
                  'Format': {
                    'sentAs': 'Format'
                  },
                  'Bucket': {
                    'sentAs': 'Bucket'
                  },
                  'Prefix': {
                    'sentAs': 'Prefix'
                  }

                }
              },
              'Schedule': {
                'type': 'object',
                'sentAs': 'Schedule',
                'parameters': {
                  'Frequency': {
                    'sentAs': 'Frequency'
                  }
                }
              },
              'IncludedObjectVersions': {
                'sentAs': 'IncludedObjectVersions'
              },
              'OptionalFields': {
                'type': 'object',
                'location': 'xml',
                'sentAs': 'OptionalFields',
                'parameters': {
                  'Field': {
                    'type': 'array',
                    'sentAs': 'Field',
                    'items': {
                      'type': 'string'
                    }
                  }
                }
              },
              'LastExportTime': {
                'sentAs': 'LastExportTime'
              }
            }

          }
        }

      }
    },
    'SetBucketInventory': {
      'httpMethod': 'PUT',
      'urlPath': 'inventory',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'

        },
        'Id': {
          'location': 'urlPath',
          'sentAs': 'id'
        },
        'InventoryConfiguration': InventoryConfiguration

      }
    },
    'SetBucketInventoryOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'InventoryConfiguration'

      },
      'parameters': {
        'InventoryConfiguration': InventoryConfiguration
      }

    },
    'DeleteInventory': {
      'httpMethod': 'DELETE',
      'urlPath': 'inventory',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Id': {
          'location': 'urlPath',
          'sentAs': 'id'
        }
      }
    },
    'DeleteInventoryOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'InventoryConfiguration'

      },
      'parameters': {
        'InventoryConfiguration': InventoryConfiguration
      }

    },
    'GetBucketEncryption': {
      'httpMethod': 'GET',
      'urlPath': 'encryption',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketEncryptionOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ServerSideEncryptionConfiguration'
      },
      'parameters': {
        'Rule': {
          'type': 'object',
          'location': 'xml',
          'sentAs': 'Rule',

          'parameters': {
            'ApplyServerSideEncryptionByDefault': {
              'type': 'object',
              'sentAs': 'ApplyServerSideEncryptionByDefault',
              'parameters': {
                'SSEAlgorithm': {
                  'sentAs': 'SSEAlgorithm'
                },
                'KMSMasterKeyID': {
                  'sentAs': 'KMSMasterKeyID'
                },
                'ProjectID': {
                  'sentAs': 'ProjectID'
                }
              }
            }
          }
        }
      }
    },
    'SetBucketEncryption': {
      'httpMethod': 'PUT',
      'urlPath': 'encryption',
      'data': {
        'xmlRoot': 'ServerSideEncryptionConfiguration'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Rule': bucketEncryptionRule
      }
    },
    'SetBucketEncryptionOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ServerSideEncryptionConfiguration'
      },
      'parameters': {
        'Rule': bucketEncryptionRule
      }
    },
    'DeleteBucketEncryption': {
      'httpMethod': 'DELETE',
      'urlPath': 'encryption',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'DeleteBucketEncryptionOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ServerSideEncryptionConfiguration'
      },
      'parameters': {
        'Rule': bucketEncryptionRule
      }
    },
    'GetBucketRequesterPay': {
      'httpMethod': 'GET',
      'urlPath': 'requestPayment',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketRequesterPayOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'RequestPaymentConfiguration'
      },
      'parameters': {
        'Payer': {
          'location': 'xml',
          'sentAs': 'Payer'
        }
      }
    },
    'SetBucketRequesterPay': {
      'httpMethod': 'PUT',
      'urlPath': 'requestPayment',
      'data': {
        'xmlRoot': 'RequestPaymentConfiguration'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Payer': {
          'location': 'xml',
          'sentAs': 'Payer'
        }
      }
    },
    'SetBucketRequesterPayOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'RequestPaymentConfiguration'
      },
      'parameters': {
        'Payer': {
          'location': 'xml',
          'sentAs': 'Payer'
        }
      }
    },
    'OptionsBucket': {
      'httpMethod': 'OPTIONS',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Origin': {
          'required': true,
          'location': 'header',
          'sentAs': 'Origin'
        },
        'AccessControlRequestMethods': {
          'required': true,
          'type': 'array',
          'location': 'header',
          'sentAs': 'Access-Control-Request-Method',
          'items': {
            'type': 'string'
          }
        },
        'AccessControlRequestHeaders': {
          'type': 'array',
          'location': 'header',
          'sentAs': 'Access-Control-Request-Headers',
          'items': {
            'type': 'string'
          }
        }
      }
    },
    'OptionsBucketOutput': {
      'parameters': {
        'AllowOrigin': {
          'location': 'header',
          'sentAs': 'access-control-allow-origin'
        },
        'AllowHeader': {
          'location': 'header',
          'sentAs': 'access-control-allow-headers'
        },
        'AllowMethod': {
          'location': 'header',
          'sentAs': 'access-control-allow-methods'
        },
        'ExposeHeader': {
          'location': 'header',
          'sentAs': 'access-control-expose-headers'
        },
        'MaxAgeSeconds': {
          'location': 'header',
          'sentAs': 'access-control-max-age'
        }
      }
    },
    'OptionsObject': {
      'httpMethod': 'OPTIONS',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'Origin': {
          'required': true,
          'location': 'header',
          'sentAs': 'Origin'
        },
        'AccessControlRequestMethods': {
          'required': true,
          'type': 'array',
          'location': 'header',
          'sentAs': 'Access-Control-Request-Method',
          'items': {
            'type': 'string'
          }
        },
        'AccessControlRequestHeaders': {
          'type': 'array',
          'location': 'header',
          'sentAs': 'Access-Control-Request-Headers',
          'items': {
            'type': 'string'
          }
        }
      }
    },
    'OptionsObjectOutput': {
      'parameters': {
        'AllowOrigin': {
          'location': 'header',
          'sentAs': 'access-control-allow-origin'
        },
        'AllowHeader': {
          'location': 'header',
          'sentAs': 'access-control-allow-headers'
        },
        'AllowMethod': {
          'location': 'header',
          'sentAs': 'access-control-allow-methods'
        },
        'ExposeHeader': {
          'location': 'header',
          'sentAs': 'access-control-expose-headers'
        },
        'MaxAgeSeconds': {
          'location': 'header',
          'sentAs': 'access-control-max-age'
        }
      }
    },

    'SetMirrorBackToSource': {
      'httpMethod': 'PUT',
      'urlPath': 'mirrorBackToSource',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        },
        'Rules': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'SetMirrorBackToSourceOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'Rules': {
          'location': 'body'
        }
      }
    },
    'GetMirrorBackToSource': {
      'httpMethod': 'GET',
      'urlPath': 'mirrorBackToSource',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        }
      }
    },
    'GetMirrorBackToSourceOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'Rules': {
          'location': 'body'
        }
      }
    },
    'deleteMirrorBackToSource': {
      'httpMethod': 'DELETE',
      'urlPath': 'mirrorBackToSource',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        }
      }
    },
    'GetBucketDirectColdAccess': {
      'httpMethod': 'GET',
      'urlPath': 'directcoldaccess',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketDirectColdAccessOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'DirectColdAccessConfiguration'
      },
      'parameters': {
        'Status': {
          'location': 'xml',
          'sentAs': 'Status'
        }
      }
    },
    'SetBucketDirectColdAccess': {
      'httpMethod': 'PUT',
      'urlPath': 'directcoldaccess',
      'data': {
        'xmlRoot': 'DirectColdAccessConfiguration',
        'md5': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Status': {
          'required': true,
          'location': 'xml',
          'sentAs': 'Status'
        }
      }
    },

    'SetBucketDirectColdAccessOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'DirectColdAccessConfiguration'
      },
      'parameters': {
        'Status': {
          'location': 'xml',
          'sentAs': 'Status'
        }
      }
    },

    'DeleteBucketDirectColdAccess': {
      'httpMethod': 'DELETE',
      'urlPath': 'directcoldaccess',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'DeleteBucketDirectColdAccessOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'DirectColdAccessConfiguration'
      },
      'parameters': {
        'Status': {
          'location': 'xml',
          'sentAs': 'Status'
        }
      }
    },
    'GetBucketCustomDomain': {
      'httpMethod': 'GET',
      'urlPath': 'customdomain',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketCustomDomainOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ListBucketCustomDomainsResult'
      },
      'parameters': {
        'Domains': {
          'location': 'xml',
          'type': 'array',
          'sentAs': 'Domains',
          'items': {
            'type': 'object',
            'parameters': {
              'DomainName': {
                'sentAs': 'DomainName'
              },
              'Value': {
                'sentAs': 'CreateTime'
              }
            }
          }
        }
      }
    },
    'SetBucketCustomDomain': {
      'httpMethod': 'PUT',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'DomainName': {
          'location': 'urlPath',
          'sentAs': 'customdomain'
        }
      }
    },
    'DeleteBucketCustomDomain': {
      'httpMethod': 'DELETE',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'DomainName': {
          'location': 'urlPath',
          'sentAs': 'customdomain'
        }
      }
    },
    'GetCDNNotifyConfiguration': {
      'httpMethod': 'GET',
      'urlPath': 'CDNNotifyConfiguration',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetCDNNotifyConfigurationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'CDNNotifyConfiguration'
      },
      'parameters': {
        'Domain': {
          'location': 'xml',
          'type': 'array',
          'sentAs': 'Domain',
          'items': {
            'type': 'object',
            'parameters': {
              'Name': {
                'sentAs': 'Name'
              },
              'Events': {
                'type': 'array',
                'items': {
                  'type': 'adapter'
                },
                'sentAs': 'Event'
              }
            }
          }
        }
      }
    },
    'SetCdnNotifyConfiguration': {
      'httpMethod': 'PUT',
      'urlPath': 'CDNNotifyConfiguration',
      'data': {
        'xmlRoot': 'CDNNotifyConfiguration',
        'xmlAllowEmpty': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'

        },
        'Domain': CDNNotifyConfiguration
      }
    },
    'GetQuota': {
      'httpMethod': 'GET',
      'urlPath': 'quota'
    },
    'GetQuotaOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'MaxBucketNumber'
      },
      'parameters': {
        'Size': {
          'location': 'xml',
          'sentAs': 'Number'
        }
      }
    },

    'GetWorkflowTrigger': {
      'httpMethod': 'GET',
      'urlPath': 'triggerpolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        }
      }
    },
    'GetWorkflowTriggerOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'rules': {
          'location': 'body'
        }
      }
    },
    'DeleteWorkflowTrigger': {
      'httpMethod': 'DELETE',
      'urlPath': 'triggerpolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        }
      }
    },
    'CreateWorkflowTrigger': {
      'httpMethod': 'PUT',
      'urlPath': 'triggerpolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        },
        'Rule': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'RestoreFailedWorkflowExecution': {
      'httpMethod': 'PUT',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'required': true,
          'location': 'uri',
          'sentAs': 'execution_name'
        },
        'GraphName': {
          'required': true,
          'location': 'urlPath',
          'sentAs': 'x-workflow-graph-name'
        }
      }
    },
    'CreateTemplate': {
      'httpMethod': 'POST',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Template': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'CreateWorkflow': {
      'httpMethod': 'POST',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'required': true,
          'location': 'uri',
          'sentAs': 'graph_name'
        },
        'Workflow_create': {
          'location': 'urlPath',
          'sentAs': 'x-workflow-create'
        },
        'Workflow': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'DeleteWorkflow': {
      'httpMethod': 'DELETE',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'location': 'uri',
          'sentAs': 'graph_name'
        }
      }
    },
    'UpdateWorkflow': {
      'httpMethod': 'PUT',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'location': 'uri',
          'sentAs': 'graph_name'
        },
        'Graph_name': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'GetWorkflowList': {
      'httpMethod': 'GET',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'location': 'uri',
          'sentAs': 'graph_name_prefix'
        },
        'XObsLimit': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'x-workflow-limit'
        },
        'XObsPrefix': {
          'location': 'urlPath',
          'sentAs': 'x-workflow-prefix'
        },
        'XObsStart': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'x-workflow-start'
        }
      }
    },
    'GetWorkflowListOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'workflows': {
          'location': 'body'
        }
      }
    },
    'GetWorkflowTemplateList': {
      'httpMethod': 'GET',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'location': 'uri',
          'sentAs': 'template_name_prefix'
        },
        'Start': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'x-workflow-start'
        },
        'Limit': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'x-workflow-limit'
        },
        'X-workflow-prefix': {
          'location': 'urlPath',
          'sentAs': 'x-workflow-prefix'
        }
      }
    },
    'GetWorkflowTemplateListOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'templates': {
          'location': 'body'
        }
      }
    },
    'GetWorkflowInstanceList': {
      'httpMethod': 'GET',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'location': 'uri',
          'sentAs': 'execution_name_prefix'
        },
        'Start': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'x-workflow-start'
        },
        'Limit': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'x-workflow-limit'
        },
        'Graph_name': {
          'location': 'urlPath',
          'sentAs': 'x-workflow-graph-name'
        },
        'State': {
          'location': 'urlPath',
          'sentAs': 'x-workflow-execution-state'
        },
        'X-workflow-prefix': {
          'location': 'urlPath',
          'sentAs': 'x-workflow-prefix'
        }
      }
    },
    'GetWorkflowInstanceListOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'instances': {
          'location': 'body'
        }
      }
    },
    'DeleteTemplate': {
      'httpMethod': 'DELETE',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'location': 'uri',
          'sentAs': 'template_name'
        }
      }
    },
    'GetActionTemplates': {
      'httpMethod': 'GET',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'location': 'uri',
          'sentAs': 'template_name_prefix'
        },
        'XObsPrefix': {
          'location': 'urlPath',
          'sentAs': 'x-workflow-prefix'
        },
        'XObsCategory': {
          'type': 'String',
          'location': 'urlPath',
          'sentAs': 'x-workflow-category'
        }
      }
    },
    'GetActionTemplatesOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'templates': {
          'location': 'body'
        }
      }
    },
    'GetWorkflowAuthorization': {
      'httpMethod': 'GET',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        }
      }

    },
    'GetWorkflowAuthorizationOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'authorization': {
          'location': 'body'
        }
      }
    },
    'OpenWorkflowAuthorization': {
      'httpMethod': 'POST',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        }
      }
    },

    'CreateOnlineDecom': {
      'httpMethod': 'PUT',
      'urlPath': 'obscompresspolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Decom': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'GetOnlineDecom': {
      'httpMethod': 'GET',
      'urlPath': 'obscompresspolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetOnlineDecomOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'Decom': {
          'location': 'body'
        }
      }
    },
    'DeleteOnlineDecom': {
      'httpMethod': 'DELETE',
      'urlPath': 'obscompresspolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    }

  }

  return operations
});
/**
 * Copyright 2019 Huawei Technologies Co.,Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
 * this file except in compliance with the License.  You may obtain a copy of the
 * License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 */

(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    define('obsModel', [], factory)
  } else {
    root['obsModel'] = factory()
  }
})(undefined || window, function() {
  var owner = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'Owner',
    'parameters': {
      'ID': {
        'sentAs': 'ID'
      }
    }
  }

  var initiator = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'Initiator',
    'parameters': {
      'ID': {
        'sentAs': 'ID'
      }
    }
  }

  var BackToSourceRules = {
    'sentAs': 'BackToSourceRule',
    'required': true,
    'location': 'xml',
    'type': 'array',
    'items': {
      'type': 'object',
      'parameters': {
        'ID': {
          'sentAs': 'ID'
        },
        'Condition': {
          'sentAs': 'Condition',
          'type': 'object',
          'parameters': {
            'ObjectKeyPrefixEquals': {
              'sentAs': 'ObjectKeyPrefixEquals'
            },
            'HttpErrorCodeReturnedEquals': {
              'sentAs': 'HttpErrorCodeReturnedEquals'
            }
          }
        },
        'Redirect': {
          'sentAs': 'Redirect',
          'type': 'object',
          'parameters': {
            'HttpRedirectCode': {
              'sentAs': 'HttpRedirectCode'
            },
            'SourceEndpoint': {
              'sentAs': 'SourceEndpoint'
            },
            'SourceBucketName': {
              'sentAs': 'SourceBucketName'
            },
            'ReplaceKeyWith': {
              'sentAs': 'ReplaceKeyWith'
            },
            'StaticUri': {
              'sentAs': 'StaticUri'
            },
            'ReplaceKeyPrefixWith': {
              'sentAs': 'ReplaceKeyPrefixWith'
            },
            'MigrationConfiguration': {
              'sentAs': 'MigrationConfiguration',
              'type': 'object',
              'parameters': {
                'Agency': {
                  'sentAs': 'Agency'
                },
                'LogBucketName': {
                  'sentAs': 'LogBucketName'
                },
                'PrivateBucketConfiguration': {
                  'sentAs': 'PrivateBucketConfiguration',
                  'type': 'object',
                  'parameters': {
                    'SourceStorageProvider': {
                      'sentAs': 'SourceStorageProvider'
                    },
                    'SourceBucketAK': {
                      'sentAs': 'SourceBucketAK'
                    },
                    'SourceBucketSK': {
                      'sentAs': 'SourceBucketSK'
                    },
                    'SourceBucketZone': {
                      'sentAs': 'SourceBucketZone'
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  var commonPrefixes = {
    'type': 'array',
    'location': 'xml',
    'sentAs': 'CommonPrefixes',
    'items': {
      'type': 'object',
      'parameters': {
        'Prefix': {
          'decode': true,
          'sentAs': 'Prefix'
        },
        'MTime': {
          'sentAs': 'MTime'
        },
        'InodeNo': {
          'sentAs': 'InodeNo'
        }
      }
    }
  }

  var grants = {
    'type': 'array',
    'location': 'xml',
    'wrapper': 'AccessControlList',
    'sentAs': 'Grant',
    'items': {
      'type': 'object',
      'parameters': {
        'Grantee': {
          'type': 'object',
          'sentAs': 'Grantee',
          'parameters': {
            'Type': {
              'type': 'ignore'
            },
            'ID': {
              'sentAs': 'ID',
              'notAllowEmpty': true
            },
            'URI': {
              'sentAs': 'Canned',
              'type': 'adapter',
              'notAllowEmpty': true
            }
          }
        },
        'Permission': {
          'sentAs': 'Permission'
        },
        'Delivered': {
          'sentAs': 'Delivered'
        }
      }
    }
  }

  var loggingEnabled = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'LoggingEnabled',
    'parameters': {
      'TargetBucket': {
        'sentAs': 'TargetBucket'
      },
      'TargetPrefix': {
        'sentAs': 'TargetPrefix'
      },
      'TargetGrants': {
        'type': 'array',
        'wrapper': 'TargetGrants',
        'sentAs': 'Grant',
        'items': {
          'type': 'object',
          'parameters': {
            'Grantee': {
              'type': 'object',
              'sentAs': 'Grantee',
              'parameters': {
                'Type': {
                  'type': 'ignore'
                },
                'ID': {
                  'sentAs': 'ID'
                },
                'URI': {
                  'sentAs': 'Canned',
                  'type': 'adapter'
                }
              }
            },
            'Permission': {
              'sentAs': 'Permission'
            }
          }
        }
      }
    }
  }

  var rules = {
    'required': true,
    'type': 'array',
    'location': 'xml',
    'sentAs': 'Rule',
    'items': {
      'type': 'object',
      'parameters': {
        'ID': {
          'sentAs': 'ID'
        },
        'Prefix': {
          'sentAs': 'Prefix'
        },
        'Status': {
          'sentAs': 'Status'
        },
        'Transitions': {
          'type': 'array',
          'sentAs': 'Transition',
          'items': {
            'type': 'object',
            'parameters': {
              'StorageClass': {
                'sentAs': 'StorageClass',
                'type': 'adapter'
              },
              'Date': {
                'sentAs': 'Date'
              },
              'Days': {
                'type': 'number',
                'sentAs': 'Days'
              }
            }
          }
        },
        'Expiration': {
          'type': 'object',
          'sentAs': 'Expiration',
          'parameters': {
            'Date': {
              'sentAs': 'Date'
            },
            'Days': {
              'type': 'number',
              'sentAs': 'Days'
            }
          }
        },
        'AbortIncompleteMultipartUpload': {
          'type': 'object',
          'sentAs': 'AbortIncompleteMultipartUpload',
          'parameters': {
            'DaysAfterInitiation': {
              'type': 'number',
              'sentAs': 'DaysAfterInitiation'
            }
          }
        },
        'NoncurrentVersionTransitions': {
          'type': 'array',
          'sentAs': 'NoncurrentVersionTransition',
          'items': {
            'type': 'object',
            'parameters': {
              'StorageClass': {
                'sentAs': 'StorageClass',
                'type': 'adapter'
              },
              'NoncurrentDays': {
                'type': 'number',
                'sentAs': 'NoncurrentDays'
              }
            }
          }
        },
        'NoncurrentVersionExpiration': {
          'type': 'object',
          'sentAs': 'NoncurrentVersionExpiration',
          'parameters': {
            'NoncurrentDays': {
              'type': 'number',
              'sentAs': 'NoncurrentDays'
            }
          }
        }
      }
    }
  }

  var redirectAllRequestsTo = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'RedirectAllRequestsTo',
    'parameters': {
      'HostName': {
        'sentAs': 'HostName'
      },
      'Protocol': {
        'sentAs': 'Protocol'
      }
    }
  }

  var routingRules = {
    'type': 'array',
    'wrapper': 'RoutingRules',
    'location': 'xml',
    'sentAs': 'RoutingRule',
    'items': {
      'type': 'object',
      'parameters': {
        'Condition': {
          'type': 'object',
          'sentAs': 'Condition',
          'parameters': {
            'HttpErrorCodeReturnedEquals': {
              'sentAs': 'HttpErrorCodeReturnedEquals'
            },
            'KeyPrefixEquals': {
              'sentAs': 'KeyPrefixEquals'
            }
          }
        },
        'Redirect': {
          'type': 'object',
          'sentAs': 'Redirect',
          'parameters': {
            'HostName': {
              'sentAs': 'HostName'
            },
            'HttpRedirectCode': {
              'sentAs': 'HttpRedirectCode'
            },
            'Protocol': {
              'sentAs': 'Protocol'
            },
            'ReplaceKeyPrefixWith': {
              'sentAs': 'ReplaceKeyPrefixWith'
            },
            'ReplaceKeyWith': {
              'sentAs': 'ReplaceKeyWith'
            }
          }
        }
      }
    }
  }

  var indexDocument = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'IndexDocument',
    'parameters': {
      'Suffix': {
        'sentAs': 'Suffix'
      }
    }
  }

  var errorDocument = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'ErrorDocument',
    'parameters': {
      'Key': {
        'sentAs': 'Key'
      }
    }
  }

  var corsRule = {
    'required': true,
    'type': 'array',
    'location': 'xml',
    'sentAs': 'CORSRule',
    'items': {
      'type': 'object',
      'parameters': {
        'ID': {
          'sentAs': 'ID'
        },
        'AllowedMethod': {
          'type': 'array',
          'sentAs': 'AllowedMethod',
          'items': {
            'type': 'string'
          }
        },
        'AllowedOrigin': {
          'type': 'array',
          'sentAs': 'AllowedOrigin',
          'items': {
            'type': 'string'
          }
        },
        'AllowedHeader': {
          'type': 'array',
          'sentAs': 'AllowedHeader',
          'items': {
            'type': 'string'
          }
        },
        'MaxAgeSeconds': {
          'type': 'number',
          'sentAs': 'MaxAgeSeconds'
        },
        'ExposeHeader': {
          'type': 'array',
          'sentAs': 'ExposeHeader',
          'items': {
            'type': 'string'
          }
        }
      }
    }
  }

  var functionGraphConfiguration = {
    'type': 'array',
    'location': 'xml',
    'sentAs': 'FunctionGraphConfiguration',
    'items': {
      'type': 'object',
      'location': 'xml',
      'parameters': {
        'ID': {
          'sentAs': 'Id'
        },
        'Filter': {
          'type': 'object',
          'parameters': {
            'FilterRules': {
              'wrapper': 'Object',
              'type': 'array',
              'sentAs': 'FilterRule',
              'items': {
                'type': 'object',
                'parameters': {
                  'Name': {},
                  'Value': {}
                }
              }
            }
          }
        },
        'FunctionGraph': {},

        'Event': {
          'type': 'array',
          'items': {
            'type': 'adapter'
          }
        }
      }
    }
  }

  var topicConfiguration = {
    'type': 'array',
    'location': 'xml',
    'sentAs': 'TopicConfiguration',
    'items': {
      'type': 'object',
      'location': 'xml',
      'parameters': {
        'ID': {
          'sentAs': 'Id'
        },
        'Filter': {
          'type': 'object',
          'parameters': {
            'FilterRules': {
              'wrapper': 'Object',
              'type': 'array',
              'sentAs': 'FilterRule',
              'items': {
                'type': 'object',
                'parameters': {
                  'Name': {},
                  'Value': {}
                }
              }
            }
          }
        },
        'Topic': {},

        'Event': {
          'type': 'array',
          'items': {
            'type': 'adapter'
          }
        }
      }
    }
  }

  var functionStageConfiguration = {
    'type': 'array',
    'location': 'xml',
    'sentAs': 'FunctionStageConfiguration',
    'items': {
      'type': 'object',
      'location': 'xml',
      'parameters': {
        'ID': {
          'sentAs': 'Id'
        },
        'Filter': {
          'type': 'object',
          'parameters': {
            'FilterRules': {
              'wrapper': 'Object',
              'type': 'array',
              'sentAs': 'FilterRule',
              'items': {
                'type': 'object',
                'parameters': {
                  'Name': {},
                  'Value': {}
                }
              }
            }
          }
        },
        'FunctionStage': {},

        'Event': {
          'type': 'array',
          'items': {
            'type': 'adapter'
          }
        }
      }
    }
  }

  var tagSet = {
    'required': true,
    'type': 'array',
    'location': 'xml',
    'wrapper': 'TagSet',
    'sentAs': 'Tag',
    'items': {
      'type': 'object',
      'parameters': {
        'Key': {
          'sentAs': 'Key'
        },
        'Value': {
          'sentAs': 'Value'
        }
      }
    }
  }

  var replicationRules = {
    'required': true,
    'type': 'array',
    'location': 'xml',
    'sentAs': 'Rule',
    'items': {
      'type': 'object',
      'parameters': {
        'ID': {
          'sentAs': 'ID'
        },
        'Prefix': {
          'sentAs': 'Prefix'
        },
        'Status': {
          'sentAs': 'Status'
        },
        'Destination': {
          'type': 'object',
          'sentAs': 'Destination',
          'parameters': {
            'Bucket': {
              'sentAs': 'Bucket',
              'type': 'adapter'
            },
            'StorageClass': {
              'sentAs': 'StorageClass',
              'type': 'adapter'
            }
          }
        },
        'HistoricalObjectReplication': {
          'sentAs': 'HistoricalObjectReplication'
        }
      }
    }
  }
  var bucketEncryptionRule = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'Rule',
    'parameters': {
      'ApplyServerSideEncryptionByDefault': {
        'type': 'object',
        'sentAs': 'ApplyServerSideEncryptionByDefault',
        'parameters': {
          'SSEAlgorithm': {
            'sentAs': 'SSEAlgorithm'
          },
          'KMSMasterKeyID': {
            'sentAs': 'KMSMasterKeyID'
          },
          'ProjectID': {
            'sentAs': 'ProjectID'
          }
        }
      }
    }
  }

  var InventoryConfiguration = {
    'type': 'object',
    'location': 'xml',
    'sentAs': 'InventoryConfiguration',
    'parameters': {
      'Id': {
        'sentAs': 'Id'

      },
      'IsEnabled': {
        'sentAs': 'IsEnabled'

      },
      'Filter': {
        'type': 'object',
        'sentAs': 'Filter',
        'parameters': {
          'Prefix': {
            'sentAs': 'Prefix'
          }
        }
      },
      'Destination': {
        'type': 'object',
        'sentAs': 'Destination',
        'parameters': {
          'Format': {
            'sentAs': 'Format'
          },
          'Bucket': {
            'sentAs': 'Bucket'
          },
          'Prefix': {
            'sentAs': 'Prefix'
          },
          'Encryption': {
            'type': 'object',
            'sentAs': 'Encryption',
            'parameters': {
              'SSE-KMS': {
                'type': 'object',
                'sentAs': 'SSE-KMS',
                'parameters': {
                  'KeyId': {
                    'sentAs': 'KeyId',
                    'type': 'adapter'
                  }
                }
              }
            }
          }
        }
      },
      'Schedule': {
        'type': 'object',
        'sentAs': 'Schedule',
        'parameters': {
          'Frequency': {
            'sentAs': 'Frequency'
          }
        }
      },
      'IncludedObjectVersions': {
        'sentAs': 'IncludedObjectVersions'
      },
      'OptionalFields': {
        'type': 'object',
        'location': 'xml',
        'sentAs': 'OptionalFields',
        'parameters': {
          'Field': {
            'type': 'array',
            'sentAs': 'Field',
            'items': {
              'type': 'string'
            }
          }
        }
      }
    }
  }
  var CDNNotifyConfiguration = {
    'location': 'xml',
    'sentAs': 'Domain',
    'type': 'array',
    'items': {
      'type': 'object',
      'parameters': {
        'Name': {
          'type': 'string',
          'sentAs': 'Name'
        },
        'Event': {
          'type': 'array',
          'items': {
            'type': 'adapter'
          },
          'sentAs': 'Event'

        }
      }
    }
  }

  var operations = {

    'HeadBucket': {
      'httpMethod': 'HEAD',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'HeadApiVersion': {
      'httpMethod': 'HEAD',
      'urlPath': 'apiversion',
      'parameters': {
        'Bucket': {
          'location': 'uri'
        }
      }
    },

    'HeadApiVersionOutput': {
      'parameters': {
        'ApiVersion': {
          'location': 'header',
          'sentAs': 'x-obs-api'
        }
      }
    },

    'CreateBucket': {
      'httpMethod': 'PUT',
      'data': {
        'xmlRoot': 'CreateBucketConfiguration'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ACL': {
          'location': 'header',
          'sentAs': 'acl',
          'withPrefix': true
        },
        'StorageType': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true
        },
        'FileInterface': {
          'location': 'header',
          'sentAs': 'fs-file-interface',
          'withPrefix': true
        },
        'Type': {
          'location': 'header',
          'sentAs': 'bucket-type',
          'withPrefix': true
        },
        'MultiAz': {
          'location': 'header',
          'sentAs': 'az-redundancy',
          'withPrefix': true
        },
        'Cluster': {
          'location': 'header',
          'sentAs': 'location-clustergroup-id',
          'withPrefix': true
        },
        'GrantFullControl': {
          'location': 'header',
          'sentAs': 'grant-full-control',
          'withPrefix': true
        },
        'GrantRead': {
          'location': 'header',
          'sentAs': 'grant-read',
          'withPrefix': true
        },
        'GrantReadACP': {
          'location': 'header',
          'sentAs': 'grant-read-acp',
          'withPrefix': true
        },
        'GrantWrite': {
          'location': 'header',
          'sentAs': 'grant-write',
          'withPrefix': true
        },
        'GrantWriteACP': {
          'location': 'header',
          'sentAs': 'grant-write-acp',
          'withPrefix': true
        },
        'ClusterType': {
          'location': 'header',
          'sentAs': 'cluster-type',
          'withPrefix': true
        },
        'MultiEnterprise': { 'location': 'header', 'sentAs': 'epid', 'withPrefix': true },
        'Location': {
          'location': 'xml',
          'sentAs': 'Location'
        }
      }
    },

    'GetBucketMetadata': {
      'httpMethod': 'HEAD',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Origin': {
          'location': 'header',
          'sentAs': 'Origin'
        },

        'RequestHeader': {
          'location': 'header',
          'sentAs': 'Access-Control-Request-Headers'
        }
      }
    },

    'GetBucketMetadataOutput': {
      'parameters': {
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true
        },
        'ObsVersion': {
          'location': 'header',
          'sentAs': 'version',
          'withPrefix': true
        },
        'Location': {
          'location': 'header',
          'sentAs': 'bucket-location',
          'withPrefix': true
        },
        'FileInterface': {
          'location': 'header',
          'sentAs': 'fs-file-interface',
          'withPrefix': true
        },
        'Type': {
          'location': 'header',
          'sentAs': 'bucket-type',
          'withPrefix': true
        },
        'MultiAz': {
          'location': 'header',
          'sentAs': 'az-redundancy',
          'withPrefix': true
        },
        'Cluster': {
          'location': 'header',
          'sentAs': 'location-clustergroup-id',
          'withPrefix': true
        },
        'MultiEnterprise': {
          'location': 'header',
          'sentAs': 'epid',
          'withPrefix': true
        },
        'ClusterType': {
          'location': 'header',
          'sentAs': 'cluster-type',
          'withPrefix': true
        },
        'AllowOrigin': {
          'location': 'header',
          'sentAs': 'access-control-allow-origin'
        },
        'MaxAgeSeconds': {
          'location': 'header',
          'sentAs': 'access-control-max-age'
        },
        'ExposeHeader': {
          'location': 'header',
          'sentAs': 'access-control-expose-headers'
        },
        'AllowMethod': {
          'location': 'header',
          'sentAs': 'access-control-allow-methods'
        },
        'AllowHeader': {
          'location': 'header',
          'sentAs': 'access-control-allow-headers'
        }
      }
    },

    'DeleteBucket': {
      'httpMethod': 'DELETE',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'ListBuckets': {
      'httpMethod': 'GET',
      'parameters': {
        'Type': {
          'sentAs': 'x-obs-bucket-type',
          'location': 'header'
        },
        'Location': {
          'sentAs': 'location',
          'location': 'header',
          'withPrefix': true
        }
      }
    },
    'ListBucketsOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ListAllMyBucketsResult'
      },
      'parameters': {
        Buckets: {
          location: 'xml',
          sentAs: 'Bucket',
          type: 'array',
          wrapper: 'Buckets',
          items: {
            type: 'object',
            location: 'xml',
            sentAs: 'Bucket',
            parameters: {
              Name: {
                sentAs: 'Name'
              },
              CreationDate: {
                sentAs: 'CreationDate'
              },
              Location: {
                sentAs: 'Location'
              },
              ClusterType: {
                sentAs: 'ClusterType'
              }
            }
          }
        },
        'Owner': {
          'type': 'object',
          'location': 'xml',
          'sentAs': 'Owner',
          'parameters': {
            'ID': {
              'sentAs': 'ID'
            },
            'DisplayName': {
              'sentAs': 'DisplayName'
            }
          }
        }
      }
    },

    'ListObjects': {
      'httpMethod': 'GET',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Prefix': {
          'location': 'urlPath',
          'sentAs': 'prefix'
        },
        'Marker': {
          'location': 'urlPath',
          'sentAs': 'marker'
        },
        'MaxKeys': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'max-keys'
        },
        'Delimiter': {
          'location': 'urlPath',
          'sentAs': 'delimiter'
        },
        'EncodingType': {
          'location': 'urlPath',
          'sentAs': 'encoding-type'
        }
      }
    },

    'ListObjectsOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ListBucketResult'
      },
      'parameters': {
        'Location': {
          'location': 'header',
          'sentAs': 'bucket-location',
          'withPrefix': true
        },
        'Bucket': {
          'location': 'xml',
          'sentAs': 'Name'
        },
        'Delimiter': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Delimiter'
        },
        'IsTruncated': {
          'location': 'xml',
          'sentAs': 'IsTruncated'
        },
        'Prefix': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Prefix'
        },
        'Marker': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Marker'
        },
        'NextMarker': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'NextMarker'
        },
        'MaxKeys': {
          'location': 'xml',
          'sentAs': 'MaxKeys'
        },
        'EncodingType': {
          'location': 'xml',
          'sentAs': 'EncodingType'
        },
        'Contents': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Contents',
          'items': {
            'type': 'object',
            'parameters': {
              'Key': {
                'decode': true,
                'sentAs': 'Key'
              },
              'LastModified': {
                'sentAs': 'LastModified'
              },
              'ETag': {
                'sentAs': 'ETag'
              },
              'Size': {
                'sentAs': 'Size'
              },
              'Type': {
                'sentAs': 'Type'
              },
              'StorageClass': {
                'sentAs': 'StorageClass'
              },
              'Owner': owner
            }
          }

        },
        'CommonPrefixes': commonPrefixes
      }
    },

    'ListVersions': {
      'httpMethod': 'GET',
      'urlPath': 'versions',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Prefix': {
          'location': 'urlPath',
          'sentAs': 'prefix'
        },
        'KeyMarker': {
          'location': 'urlPath',
          'sentAs': 'key-marker'
        },
        'MaxKeys': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'max-keys'
        },
        'Delimiter': {
          'location': 'urlPath',
          'sentAs': 'delimiter'
        },
        'VersionIdMarker': {
          'location': 'urlPath',
          'sentAs': 'version-id-marker'
        },
        'EncodingType': {
          'location': 'urlPath',
          'sentAs': 'encoding-type'
        }
      }
    },

    'ListVersionsOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ListVersionsResult'
      },
      'parameters': {
        'EncodingType': {
          'location': 'xml',
          'sentAs': 'EncodingType'
        },
        'Location': {
          'location': 'header',
          'sentAs': 'bucket-location',
          'withPrefix': true
        },
        'Bucket': {
          'location': 'xml',
          'sentAs': 'Name'
        },
        'Prefix': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Prefix'
        },
        'Delimiter': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Delimiter'
        },
        'KeyMarker': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'KeyMarker'
        },
        'VersionIdMarker': {
          'location': 'xml',
          'sentAs': 'VersionIdMarker'
        },
        'NextKeyMarker': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'NextKeyMarker'
        },
        'NextVersionIdMarker': {
          'location': 'xml',
          'sentAs': 'NextVersionIdMarker'
        },
        'MaxKeys': {
          'location': 'xml',
          'sentAs': 'MaxKeys'
        },
        'IsTruncated': {
          'location': 'xml',
          'sentAs': 'IsTruncated'
        },
        'Versions': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Version',
          'items': {
            'type': 'object',
            'parameters': {
              'Key': {
                'decode': true,
                'sentAs': 'Key'
              },
              'VersionId': {
                'sentAs': 'VersionId'
              },
              'IsLatest': {
                'sentAs': 'IsLatest'
              },
              'LastModified': {
                'sentAs': 'LastModified'
              },
              'ETag': {
                'sentAs': 'ETag'
              },
              'Size': {
                'sentAs': 'Size'
              },
              'Type': {
                'sentAs': 'Type'
              },
              'Owner': owner,
              'StorageClass': {
                'sentAs': 'StorageClass'
              }
            }
          }
        },
        'DeleteMarkers': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'DeleteMarker',
          'items': {
            'type': 'object',
            'parameters': {
              'Key': {
                'decode': true,
                'sentAs': 'Key'
              },
              'VersionId': {
                'sentAs': 'VersionId'
              },
              'IsLatest': {
                'sentAs': 'IsLatest'
              },
              'LastModified': {
                'sentAs': 'LastModified'
              },
              'Owner': owner
            }
          }
        },
        'CommonPrefixes': commonPrefixes
      }
    },

    'PutBackToSource': {
      'httpMethod': 'PUT',
      'data': {
        'xmlRoot': 'BackToSourceConfiguration'
      },
      'urlPath': 'backtosource',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'BackToSourceRules': BackToSourceRules,
        'ContentMD5': {
          'location': 'header',
          'sentAs': 'Content-MD5'
        }
      }
    },

    'DeleteBackToSource': {
      'httpMethod': 'DELETE',
      'urlPath': 'backtosource',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBackToSource': {
      'httpMethod': 'GET',
      'urlPath': 'backtosource',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBackToSourceOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'BackToSourceConfiguration'
      },
      'parameters': {
        'BackToSourceRules': BackToSourceRules
      }
    },

    'GetBucketLocation': {
      'httpMethod': 'GET',
      'urlPath': 'location',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketLocationOutput': {
      'data': {
        'type': 'xml'
      },
      'parameters': {
        'Location': {
          'location': 'xml',
          'sentAs': 'Location'
        }
      }
    },

    'GetBucketStorageInfo': {
      'httpMethod': 'GET',
      'urlPath': 'storageinfo',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketStorageInfoOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'GetBucketStorageInfoResult'
      },
      'parameters': {
        'Size': {
          'location': 'xml',
          'sentAs': 'Size'
        },
        'ObjectNumber': {
          'location': 'xml',
          'sentAs': 'ObjectNumber'
        }
      }
    },

    'SetBucketQuota': {
      'httpMethod': 'PUT',
      'urlPath': 'quota',
      'data': {
        'xmlRoot': 'Quota'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'StorageQuota': {
          'required': true,
          'location': 'xml',
          'sentAs': 'StorageQuota'
        }
      }
    },

    'GetBucketQuota': {
      'httpMethod': 'GET',
      'urlPath': 'quota',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }

      }
    },
    'GetBucketQuotaOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'Quota'
      },
      'parameters': {
        'StorageQuota': {
          'location': 'xml',
          'sentAs': 'StorageQuota'
        }
      }
    },

    'SetBucketAcl': {
      'httpMethod': 'PUT',
      'urlPath': 'acl',
      'data': {
        'xmlRoot': 'AccessControlPolicy'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ACL': {
          'location': 'header',
          'sentAs': 'acl',
          'withPrefix': true,
          'type': 'adapter'
        },
        'Owner': owner,
        'Grants': grants
      }
    },

    'GetBucketInventory': {
      'httpMethod': 'GET',
      'urlPath': 'inventory',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketInventoryOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ListInventoryConfiguration'

      },
      'parameters': {
        'Rules': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'InventoryConfiguration',
          'items': {
            'type': 'object',
            'parameters': {
              'Id': {
                'sentAs': 'Id'

              },
              'IsEnabled': {
                'sentAs': 'IsEnabled'

              },
              'Filter': {
                'type': 'object',
                'sentAs': 'Filter',
                'parameters': {
                  'Prefix': {
                    'sentAs': 'Prefix'
                  }
                }
              },
              'Destination': {
                'type': 'object',
                'sentAs': 'Destination',
                'parameters': {
                  'Format': {
                    'sentAs': 'Format'
                  },
                  'Bucket': {
                    'sentAs': 'Bucket'
                  },
                  'Prefix': {
                    'sentAs': 'Prefix'
                  }

                }
              },
              'Schedule': {
                'type': 'object',
                'sentAs': 'Schedule',
                'parameters': {
                  'Frequency': {
                    'sentAs': 'Frequency'
                  }
                }
              },
              'IncludedObjectVersions': {
                'sentAs': 'IncludedObjectVersions'
              },
              'OptionalFields': {
                'type': 'object',
                'location': 'xml',
                'sentAs': 'OptionalFields',
                'parameters': {
                  'Field': {
                    'type': 'array',
                    'sentAs': 'Field',
                    'items': {
                      'type': 'string'
                    }
                  }
                }
              },
              'LastExportTime': {
                'sentAs': 'LastExportTime'
              }
            }

          }
        }

      }
    },
    'SetBucketInventory': {
      'httpMethod': 'PUT',
      'urlPath': 'inventory',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'

        },
        'Id': {
          'location': 'urlPath',
          'sentAs': 'id'
        },
        'InventoryConfiguration': InventoryConfiguration

      }
    },
    'SetBucketInventoryOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'InventoryConfiguration'

      },
      'parameters': {
        'InventoryConfiguration': InventoryConfiguration
      }
    },

    'DeleteBucketInventory': {
      'httpMethod': 'DELETE',
      'urlPath': 'inventory',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Id': {
          'location': 'urlPath',
          'sentAs': 'id'
        }
      }
    },
    'DeleteBucketInventoryOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'InventoryConfiguration'
      },
      'parameters': {
        'InventoryConfiguration': InventoryConfiguration
      }
    },

    'GetBucketAcl': {
      'httpMethod': 'GET',
      'urlPath': 'acl',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketAclOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'AccessControlPolicy'
      },
      'parameters': {
        'Owner': owner,
        'Grants': grants
      }
    },

    'SetBucketLoggingConfiguration': {
      'httpMethod': 'PUT',
      'urlPath': 'logging',
      'data': {
        'xmlRoot': 'BucketLoggingStatus',
        'xmlAllowEmpty': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Agency': {
          'location': 'xml',
          'sentAs': 'Agency'
        },
        'LoggingEnabled': loggingEnabled
      }
    },

    'GetBucketLoggingConfiguration': {
      'httpMethod': 'GET',
      'urlPath': 'logging',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketLoggingConfigurationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'BucketLoggingStatus'
      },
      'parameters': {
        'Agency': {
          'location': 'xml',
          'sentAs': 'Agency'
        },
        'LoggingEnabled': loggingEnabled
      }
    },

    'SetSFSAcl': {
      'httpMethod': 'PUT',
      'urlPath': 'sfsacl',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Policy': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'GetSFSAcl': {
      'httpMethod': 'GET',
      'urlPath': 'sfsacl',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetSFSAclOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'Policy': {
          'location': 'body'
        }
      }
    },
    'DeleteSFSAcl': {
      'httpMethod': 'DELETE',
      'urlPath': 'sfsacl',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'SetBucketPolicy': {
      'httpMethod': 'PUT',
      'urlPath': 'policy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Policy': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'GetBucketPolicy': {
      'httpMethod': 'GET',
      'urlPath': 'policy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketPolicyOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'Policy': {
          'location': 'body'
        }
      }
    },
    'DeleteBucketPolicy': {
      'httpMethod': 'DELETE',
      'urlPath': 'policy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'SetBucketDisPolicy': {
      'httpMethod': 'PUT',
      'urlPath': 'disPolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        },
        'Rules': {
          'required': true,
          'location': 'body'
        }
      }
    },

    'GetBucketDisPolicy': {
      'httpMethod': 'GET',
      'urlPath': 'disPolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        }
      }
    },

    'GetBucketDisPolicyOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'Rules': {
          'location': 'body'
        }
      }
    },

    'DeleteBucketDisPolicy': {
      'httpMethod': 'DELETE',
      'urlPath': 'disPolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        }
      }
    },

    'SetBucketLifecycleConfiguration': {
      'httpMethod': 'PUT',
      'urlPath': 'lifecycle',
      'data': {
        'xmlRoot': 'LifecycleConfiguration',
        'md5': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Rules': rules
      }
    },

    'GetBucketLifecycleConfiguration': {
      'httpMethod': 'GET',
      'urlPath': 'lifecycle',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketLifecycleConfigurationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'LifecycleConfiguration'
      },
      'parameters': {
        'Rules': rules
      }
    },
    'DeleteBucketLifecycleConfiguration': {
      'httpMethod': 'DELETE',
      'urlPath': 'lifecycle',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'SetBucketWebsiteConfiguration': {
      'httpMethod': 'PUT',
      'urlPath': 'website',
      'data': {
        'xmlRoot': 'WebsiteConfiguration'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'RedirectAllRequestsTo': redirectAllRequestsTo,
        'IndexDocument': indexDocument,
        'ErrorDocument': errorDocument,
        'RoutingRules': routingRules
      }
    },
    'GetBucketWebsiteConfiguration': {
      'httpMethod': 'GET',
      'urlPath': 'website',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketWebsiteConfigurationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'WebsiteConfiguration'
      },
      'parameters': {
        'RedirectAllRequestsTo': redirectAllRequestsTo,
        'IndexDocument': indexDocument,
        'ErrorDocument': errorDocument,
        'RoutingRules': routingRules
      }
    },
    'DeleteBucketWebsiteConfiguration': {
      'httpMethod': 'DELETE',
      'urlPath': 'website',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'SetBucketVersioningConfiguration': {
      'httpMethod': 'PUT',
      'urlPath': 'versioning',
      'data': {
        'xmlRoot': 'VersioningConfiguration'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'VersionStatus': {
          'required': true,
          'location': 'xml',
          'sentAs': 'Status'
        }
      }
    },
    'GetBucketVersioningConfiguration': {
      'httpMethod': 'GET',
      'urlPath': 'versioning',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketVersioningConfigurationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'VersioningConfiguration'
      },
      'parameters': {
        'VersionStatus': {
          'location': 'xml',
          'sentAs': 'Status'
        }
      }
    },

    'SetBucketCors': {
      'httpMethod': 'PUT',
      'urlPath': 'cors',
      'data': {
        'xmlRoot': 'CORSConfiguration',
        'md5': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'CorsRules': corsRule
      }
    },
    'GetBucketCors': {
      'httpMethod': 'GET',
      'urlPath': 'cors',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketCorsOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'CORSConfiguration'
      },
      'parameters': {
        'CorsRules': corsRule
      }
    },
    'DeleteBucketCors': {
      'httpMethod': 'DELETE',
      'urlPath': 'cors',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'SetBucketNotification': {
      'httpMethod': 'PUT',
      'urlPath': 'notification',
      'data': {
        'xmlRoot': 'NotificationConfiguration',
        'xmlAllowEmpty': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'TopicConfigurations': topicConfiguration,
        'FunctionGraphConfigurations': functionGraphConfiguration,
        'FunctionStageConfigurations': functionStageConfiguration
      }
    },

    'GetBucketNotification': {
      'httpMethod': 'GET',
      'urlPath': 'notification',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketNotificationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'NotificationConfiguration'
      },
      'parameters': {
        'RequestId': {
          'location': 'header',
          'sentAs': 'x-obs-request-id'
        },
        'TopicConfigurations': topicConfiguration,
        'FunctionGraphConfigurations': functionGraphConfiguration,
        'FunctionStageConfigurations': functionStageConfiguration
      }
    },

    'SetBucketTagging': {
      'httpMethod': 'PUT',
      'urlPath': 'tagging',
      'data': {
        'xmlRoot': 'Tagging',
        'md5': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Tags': tagSet
      }
    },

    'DeleteBucketTagging': {
      'httpMethod': 'DELETE',
      'urlPath': 'tagging',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketTagging': {
      'httpMethod': 'GET',
      'urlPath': 'tagging',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketTaggingOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'Tagging'
      },
      'parameters': {
        'Tags': tagSet
      }
    },

    'SetBucketStoragePolicy': {
      'httpMethod': 'PUT',
      'urlPath': 'storageClass',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'StorageClass': {
          'required': true,
          'location': 'xml',
          'type': 'adapter',
          'sentAs': 'StorageClass'
        }
      }
    },

    'GetBucketStoragePolicy': {
      'httpMethod': 'GET',
      'urlPath': 'storageClass',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketStoragePolicyOutput': {
      'data': {
        'type': 'xml'
      },
      'parameters': {
        'StorageClass': {
          'location': 'xml',
          'type': 'string',
          'sentAs': 'StorageClass'
        }
      }
    },

    'SetBucketReplication': {
      'httpMethod': 'PUT',
      'urlPath': 'replication',
      'data': {
        'xmlRoot': 'ReplicationConfiguration',
        'md5': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Agency': {
          'location': 'xml',
          'sentAs': 'Agency'
        },
        'Rules': replicationRules
      }
    },

    'GetBucketReplication': {
      'httpMethod': 'GET',
      'urlPath': 'replication',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'GetBucketReplicationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ReplicationConfiguration'
      },
      'parameters': {
        'Agency': {
          'location': 'xml',
          'sentAs': 'Agency'
        },
        'Rules': replicationRules
      }
    },

    'DeleteBucketReplication': {
      'httpMethod': 'DELETE',
      'urlPath': 'replication',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'PutObject': {
      'httpMethod': 'PUT',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'ContentMD5': {
          'location': 'header',
          'sentAs': 'Content-MD5'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'Offset': {
          'type': 'plain'
        },
        'ContentLength': {
          'location': 'header',
          'sentAs': 'Content-Length',
          'type': 'plain'
        },
        'ACL': {
          'location': 'header',
          'sentAs': 'acl',
          'withPrefix': true,
          'type': 'adapter'
        },
        'GrantRead': {
          'location': 'header',
          'sentAs': 'grant-read',
          'withPrefix': true
        },
        'GrantReadAcp': {
          'location': 'header',
          'sentAs': 'grant-read-acp',
          'withPrefix': true
        },
        'GrantWriteAcp': {
          'location': 'header',
          'sentAs': 'grant-write-acp',
          'withPrefix': true
        },
        'GrantFullControl': {
          'location': 'header',
          'sentAs': 'grant-full-control',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true,
          'type': 'adapter'
        },
        'Metadata': {
          'type': 'object',
          'location': 'header',
          'sentAs': 'meta-',
          'withPrefix': true
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        },
        'Expires': {
          'location': 'header',
          'sentAs': 'expires',
          'type': 'number',
          'withPrefix': true
        },
        'SuccessActionRedirect': {
          'location': 'header',
          'sentAs': 'success-action-redirect'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true,
          'type': 'adapter'
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseKmsProjectId': {
          'location': 'header',
          'sentAs': 'sse-kms-key-project-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        },
        'Body': {
          'location': 'body'
        },
        'SourceFile': {
          'type': 'srcFile'
        },
        'ProgressCallback': {
          'type': 'plain'
        }
      }
    },
    'PutObjectOutput': {
      'parameters': {
        'ETag': {
          'location': 'header',
          'sentAs': 'etag'
        },
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseKmsProjectId': {
          'location': 'header',
          'sentAs': 'sse-kms-key-project-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        }
      }
    },

    'AppendObject': {
      'httpMethod': 'POST',
      'urlPath': 'append',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'Position': {
          'location': 'urlPath',
          'sentAs': 'position',
          'type': 'number'
        },
        'ContentMD5': {
          'location': 'header',
          'sentAs': 'Content-MD5'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'Offset': {
          'type': 'plain'
        },
        'ContentLength': {
          'location': 'header',
          'sentAs': 'Content-Length',
          'type': 'plain'
        },
        'ACL': {
          'location': 'header',
          'sentAs': 'acl',
          'withPrefix': true,
          'type': 'adapter'
        },
        'GrantRead': {
          'location': 'header',
          'sentAs': 'grant-read',
          'withPrefix': true
        },
        'GrantReadAcp': {
          'location': 'header',
          'sentAs': 'grant-read-acp',
          'withPrefix': true
        },
        'GrantWriteAcp': {
          'location': 'header',
          'sentAs': 'grant-write-acp',
          'withPrefix': true
        },
        'GrantFullControl': {
          'location': 'header',
          'sentAs': 'grant-full-control',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true,
          'type': 'adapter'
        },
        'Metadata': {
          'type': 'object',
          'location': 'header',
          'sentAs': 'meta-',
          'withPrefix': true
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        },
        'Expires': {
          'location': 'header',
          'sentAs': 'expires',
          'type': 'number',
          'withPrefix': true
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true,
          'type': 'adapter'
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        },
        'Body': {
          'location': 'body'
        },
        'SourceFile': {
          'type': 'srcFile'
        },
        'ProgressCallback': {
          'type': 'plain'
        }
      }
    },
    'AppendObjectOutput': {
      'parameters': {
        'ETag': {
          'location': 'header',
          'sentAs': 'etag'
        },
        'NextPosition': {
          'location': 'header',
          'sentAs': 'next-append-position',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        }
      }
    },

    'GetObject': {
      'httpMethod': 'GET',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'ResponseCacheControl': {
          'location': 'urlPath',
          'sentAs': 'response-cache-control'
        },
        'ResponseContentDisposition': {
          'location': 'urlPath',
          'sentAs': 'response-content-disposition'
        },
        'ResponseContentEncoding': {
          'location': 'urlPath',
          'sentAs': 'response-content-encoding'
        },
        'ResponseContentLanguage': {
          'location': 'urlPath',
          'sentAs': 'response-content-language'
        },
        'ResponseContentType': {
          'location': 'urlPath',
          'sentAs': 'response-content-type'
        },
        'ResponseExpires': {
          'location': 'urlPath',
          'sentAs': 'response-expires'
        },
        'VersionId': {
          'location': 'urlPath',
          'sentAs': 'versionId'
        },
        'ImageProcess': {
          'location': 'urlPath',
          'sentAs': 'x-image-process'
        },
        'IfMatch': {
          'location': 'header',
          'sentAs': 'If-Match'
        },
        'IfModifiedSince': {
          'location': 'header',
          'sentAs': 'If-Modified-Since'
        },
        'IfNoneMatch': {
          'location': 'header',
          'sentAs': 'If-None-Match'
        },
        'IfUnmodifiedSince': {
          'location': 'header',
          'sentAs': 'If-Unmodified-Since'
        },
        'Range': {
          'location': 'header',
          'sentAs': 'Range'
        },
        'Origin': {
          'location': 'header',
          'sentAs': 'Origin'
        },
        'RequestHeader': {
          'location': 'header',
          'sentAs': 'Access-Control-Request-Headers'
        },
        'SaveByType': {
          'type': 'dstFile'
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        },
        'ProgressCallback': {
          'type': 'plain'
        }
      }
    },
    'GetObjectOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'Content': {
          'location': 'body'
        },
        'Expiration': {
          'location': 'header',
          'sentAs': 'expiration',
          'withPrefix': true
        },
        'ETag': {
          'location': 'header',
          'sentAs': 'etag'
        },
        'CacheControl': {
          'location': 'header',
          'sentAs': 'Cache-Control'
        },
        'ContentDisposition': {
          'location': 'header',
          'sentAs': 'Content-Disposition'
        },
        'ContentEncoding': {
          'location': 'header',
          'sentAs': 'Content-Encoding'
        },
        'ContentLanguage': {
          'location': 'header',
          'sentAs': 'Content-Language'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'Expires': {
          'location': 'header',
          'sentAs': 'Expires'
        },
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        },
        'ContentLength': {
          'location': 'header',
          'sentAs': 'Content-Length'
        },
        'DeleteMarker': {
          'location': 'header',
          'sentAs': 'delete-marker',
          'withPrefix': true
        },
        'LastModified': {
          'location': 'header',
          'sentAs': 'Last-Modified'
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true
        },
        'Restore': {
          'location': 'header',
          'sentAs': 'restore',
          'withPrefix': true
        },
        'AllowOrigin': {
          'location': 'header',
          'sentAs': 'access-control-allow-origin'
        },
        'MaxAgeSeconds': {
          'location': 'header',
          'sentAs': 'access-control-max-age'
        },
        'ExposeHeader': {
          'location': 'header',
          'sentAs': 'access-control-expose-headers'
        },
        'AllowMethod': {
          'location': 'header',
          'sentAs': 'access-control-allow-methods'
        },
        'AllowHeader': {
          'location': 'header',
          'sentAs': 'access-control-allow-headers'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        },
        'Metadata': {
          'location': 'header',
          'type': 'object',
          'sentAs': 'meta-',
          'withPrefix': true
        }
      }
    },
    'CopyObject': {
      'httpMethod': 'PUT',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'ACL': {
          'location': 'header',
          'sentAs': 'acl',
          'withPrefix': true,
          'type': 'adapter'
        },
        'GrantRead': {
          'location': 'header',
          'sentAs': 'grant-read',
          'withPrefix': true
        },
        'GrantReadAcp': {
          'location': 'header',
          'sentAs': 'grant-read-acp',
          'withPrefix': true
        },
        'GrantWriteAcp': {
          'location': 'header',
          'sentAs': 'grant-write-acp',
          'withPrefix': true
        },
        'GrantFullControl': {
          'location': 'header',
          'sentAs': 'grant-full-control',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true,
          'type': 'adapter'
        },
        'CopySource': {
          'required': true,
          'location': 'header',
          'sentAs': 'copy-source',
          'withPrefix': true,
          'skipEncoding': true
        },
        'CopySourceIfMatch': {
          'location': 'header',
          'sentAs': 'copy-source-if-match',
          'withPrefix': true
        },
        'CopySourceIfModifiedSince': {
          'location': 'header',
          'sentAs': 'copy-source-if-modified-since',
          'withPrefix': true
        },
        'CopySourceIfNoneMatch': {
          'location': 'header',
          'sentAs': 'copy-source-if-none-match',
          'withPrefix': true
        },
        'CopySourceIfUnmodifiedSince': {
          'location': 'header',
          'sentAs': 'copy-source-if-unmodified-since',
          'withPrefix': true
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'ContentEncoding': {
          'location': 'header',
          'sentAs': 'content-encoding'
        },
        'ContentLanguage': {
          'location': 'header',
          'sentAs': 'content-language'
        },
        'ContentDisposition': {
          'location': 'header',
          'sentAs': 'content-disposition'
        },
        'CacheControl': {
          'location': 'header',
          'sentAs': 'cache-control'
        },
        'Expires': {
          'location': 'header',
          'sentAs': 'expires'
        },
        'Metadata': {
          'type': 'object',
          'location': 'header',
          'sentAs': 'meta-',
          'withPrefix': true
        },
        'MetadataDirective': {
          'location': 'header',
          'sentAs': 'metadata-directive',
          'withPrefix': true
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        },
        'SuccessActionRedirect': {
          'location': 'header',
          'sentAs': 'success-action-redirect'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true,
          'type': 'adapter'
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        },
        'CopySourceSseC': {
          'location': 'header',
          'sentAs': 'copy-source-server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'CopySourceSseCKey': {
          'location': 'header',
          'sentAs': 'copy-source-server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        }
      }
    },
    'CopyObjectOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'CopyObjectResult'
      },
      'parameters': {
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        },
        'CopySourceVersionId': {
          'location': 'header',
          'sentAs': 'copy-source-version-id',
          'withPrefix': true
        },
        'ETag': {
          'location': 'xml',
          'sentAs': 'ETag'
        },
        'LastModified': {
          'location': 'xml',
          'sentAs': 'LastModified'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        }
      }
    },

    'RestoreObject': {
      'httpMethod': 'POST',
      'urlPath': 'restore',
      'data': {
        'xmlRoot': 'RestoreRequest',
        'md5': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'VersionId': {
          'location': 'urlPath',
          'sentAs': 'versionId'
        },
        'Days': {
          'location': 'xml',
          'sentAs': 'Days'
        },
        'Tier': {
          'wrapper': 'RestoreJob',
          'location': 'xml',
          'sentAs': 'Tier'
        }
      }
    },

    'GetObjectMetadata': {
      'httpMethod': 'HEAD',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'VersionId': {
          'location': 'urlPath',
          'sentAs': 'versionId'
        },
        'Origin': {
          'location': 'header',
          'sentAs': 'Origin'
        },
        'RequestHeader': {
          'location': 'header',
          'sentAs': 'Access-Control-Request-Headers'
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        }
      }
    },
    'GetObjectMetadataOutput': {
      'parameters': {
        'Expiration': {
          'location': 'header',
          'sentAs': 'expiration',
          'withPrefix': true
        },
        'LastModified': {
          'location': 'header',
          'sentAs': 'Last-Modified'
        },
        'ContentLength': {
          'location': 'header',
          'sentAs': 'Content-Length'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'ETag': {
          'location': 'header',
          'sentAs': 'etag'
        },
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true
        },
        'Restore': {
          'location': 'header',
          'sentAs': 'restore',
          'withPrefix': true
        },
        'ObjectType': {
          'location': 'header',
          'sentAs': 'x-obs-object-type'
        },
        'NextPosition': {
          'location': 'header',
          'sentAs': 'x-obs-next-append-position'
        },

        'AllowOrigin': {
          'location': 'header',
          'sentAs': 'access-control-allow-origin'
        },
        'MaxAgeSeconds': {
          'location': 'header',
          'sentAs': 'access-control-max-age'
        },
        'ExposeHeader': {
          'location': 'header',
          'sentAs': 'access-control-expose-headers'
        },
        'AllowMethod': {
          'location': 'header',
          'sentAs': 'access-control-allow-methods'
        },
        'AllowHeader': {
          'location': 'header',
          'sentAs': 'access-control-allow-headers'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'x-obs-server-side-encryption-kms-key-id'
        },
        'SseKmsProjectId': {
          'location': 'header',
          'sentAs': 'sse-kms-key-project-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        },
        'Metadata': {
          'location': 'header',
          'type': 'object',
          'sentAs': 'meta-',
          'withPrefix': true
        },
        'ContentLanguage': {
          'location': 'header',
          'sentAs': 'Content-Language'
        },
        'ContentEncoding': {
          'location': 'header',
          'sentAs': 'Content-Encoding'
        },
        'CacheControl': {
          'location': 'header',
          'sentAs': 'Cache-Control'
        },
        'ContentDisposition': {
          'location': 'header',
          'sentAs': 'Content-Disposition'
        },
        'Expires': {
          'location': 'header',
          'sentAs': 'Expires'
        },
        'ReplicationStatus': {
          'location': 'header',
          'sentAs': 'replication-status',
          'withPrefix': true
        }
      }
    },

    'SetObjectMetadata': {
      'httpMethod': 'PUT',
      'urlPath': 'metadata',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'VersionId': {
          'location': 'urlPath',
          'sentAs': 'versionId'
        },
        'Origin': {
          'location': 'header',
          'sentAs': 'Origin'
        },
        'RequestHeader': {
          'location': 'header',
          'sentAs': 'Access-Control-Request-Headers'
        },
        'CacheControl': {
          'location': 'header',
          'sentAs': 'Cache-Control'
        },
        'ContentDisposition': {
          'location': 'header',
          'sentAs': 'Content-Disposition'
        },
        'ContentLanguage': {
          'location': 'header',
          'sentAs': 'Content-Language'
        },
        'ContentEncoding': {
          'location': 'header',
          'sentAs': 'Content-Encoding'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'Expires': {
          'location': 'header',
          'sentAs': 'Expires'
        },
        'Metadata': {
          'shape': 'Sy',
          'location': 'header',
          'type': 'object',
          'sentAs': 'meta-',
          'withPrefix': true
        },
        'MetadataDirective': {
          'location': 'header',
          'sentAs': 'metadata-directive',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        }
      }
    },
    'SetObjectMetadataOutput': {
      'parameters': {
        'Expires': {
          'location': 'header',
          'sentAs': 'Expires'
        },
        'ContentLength': {
          'location': 'header',
          'sentAs': 'Content-Length'
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'ContentLanguage': {
          'location': 'header',
          'sentAs': 'Content-Language'
        },
        'CacheControl': {
          'location': 'header',
          'sentAs': 'Cache-Control'
        },
        'ContentDisposition': {
          'location': 'header',
          'sentAs': 'Content-Disposition'
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true,
          'type': 'adapter'
        },
        'Metadata': {
          'location': 'header',
          'type': 'object',
          'sentAs': 'meta-',
          'withPrefix': true
        }
      }
    },

    'SetObjectAcl': {
      'httpMethod': 'PUT',
      'urlPath': 'acl',
      'data': {
        'xmlRoot': 'AccessControlPolicy'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'VersionId': {
          'location': 'urlPath',
          'sentAs': 'versionId'
        },
        'ACL': {
          'location': 'header',
          'sentAs': 'acl',
          'withPrefix': true,
          'type': 'adapter'
        },
        'Delivered': {
          'location': 'xml',
          'sentAs': 'Delivered'
        },
        'Owner': owner,
        'Grants': grants
      }
    },
    'SetObjectAclOutput': {
      'parameters': {
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        }
      }
    },
    'GetObjectAcl': {
      'httpMethod': 'GET',
      'urlPath': 'acl',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'VersionId': {
          'location': 'urlPath',
          'sentAs': 'versionId'
        }
      }
    },
    'GetObjectAclOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'AccessControlPolicy'
      },
      'parameters': {
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        },
        'Delivered': {
          'location': 'xml',
          'sentAs': 'Delivered'
        },
        'Owner': owner,
        'Grants': grants
      }
    },
    'DeleteObject': {
      'httpMethod': 'DELETE',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'VersionId': {
          'location': 'urlPath',
          'sentAs': 'versionId'
        }
      }
    },
    'DeleteObjectOutput': {
      'parameters': {
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        },
        'DeleteMarker': {
          'location': 'header',
          'sentAs': 'delete-marker',
          'withPrefix': true
        }
      }
    },
    'DeleteObjects': {
      'httpMethod': 'POST',
      'urlPath': 'delete',
      'data': {
        'xmlRoot': 'Delete',
        'md5': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Quiet': {
          'location': 'xml',
          'sentAs': 'Quiet'
        },
        'EncodingType': {
          'location': 'xml',
          'sentAs': 'EncodingType'
        },
        'Objects': {
          'required': true,
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Object',
          'items': {
            'type': 'object',
            'parameters': {
              'Key': {
                'sentAs': 'Key'
              },
              'VersionId': {
                'sentAs': 'VersionId'
              }
            }
          }
        }
      }
    },
    'DeleteObjectsOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'DeleteResult'
      },
      'EncodingType': {
        'location': 'xml',
        'sentAs': 'EncodingType'
      },
      'parameters': {
        'Deleteds': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Deleted',
          'items': {
            'type': 'object',
            'parameters': {
              'Key': {
                'decode': true,
                'sentAs': 'Key'
              },
              'VersionId': {
                'sentAs': 'VersionId'
              },
              'DeleteMarker': {
                'sentAs': 'DeleteMarker'
              },
              'DeleteMarkerVersionId': {
                'sentAs': 'DeleteMarkerVersionId'
              }
            }
          }
        },
        'Errors': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Error',
          'items': {
            'type': 'object',
            'parameters': {
              'Key': {
                'sentAs': 'Key'
              },
              'VersionId': {
                'sentAs': 'VersionId'
              },
              'Code': {
                'sentAs': 'Code'
              },
              'Message': {
                'sentAs': 'Message'
              }
            }
          }
        }
      }
    },

    'InitiateMultipartUpload': {
      'httpMethod': 'POST',
      'urlPath': 'uploads',
      'parameters': {
        'EncodingType': {
          'location': 'urlPath',
          'sentAs': 'encoding-type'
        },
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'ACL': {
          'location': 'header',
          'sentAs': 'acl',
          'withPrefix': true,
          'type': 'adapter'
        },
        'GrantRead': {
          'location': 'header',
          'sentAs': 'grant-read',
          'withPrefix': true
        },
        'GrantReadAcp': {
          'location': 'header',
          'sentAs': 'grant-read-acp',
          'withPrefix': true
        },
        'GrantWriteAcp': {
          'location': 'header',
          'sentAs': 'grant-write-acp',
          'withPrefix': true
        },
        'GrantFullControl': {
          'location': 'header',
          'sentAs': 'grant-full-control',
          'withPrefix': true
        },
        'StorageClass': {
          'location': 'header',
          'sentAs': 'storage-class',
          'withPrefix': true,
          'type': 'adapter'
        },
        'Metadata': {
          'type': 'object',
          'location': 'header',
          'sentAs': 'meta-',
          'withPrefix': true
        },
        'WebsiteRedirectLocation': {
          'location': 'header',
          'sentAs': 'website-redirect-location',
          'withPrefix': true
        },
        'Expires': {
          'location': 'header',
          'sentAs': 'expires',
          'type': 'number',
          'withPrefix': true
        },
        'ContentType': {
          'location': 'header',
          'sentAs': 'Content-Type'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true,
          'type': 'adapter'
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseKmsProjectId': {
          'location': 'header',
          'sentAs': 'sse-kms-key-project-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        }
      }
    },
    'InitiateMultipartUploadOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'InitiateMultipartUploadResult'
      },
      'parameters': {
        'EncodingType': {
          'location': 'xml',
          'sentAs': 'EncodingType'
        },
        'Bucket': {
          'location': 'xml',
          'sentAs': 'Bucket'
        },
        'Key': {
          'location': 'xml',
          'sentAs': 'Key'
        },
        'UploadId': {
          'location': 'xml',
          'sentAs': 'UploadId'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseKmsProjectId': {
          'location': 'header',
          'sentAs': 'sse-kms-key-project-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        }
      }
    },
    'ListMultipartUploads': {
      'httpMethod': 'GET',
      'urlPath': 'uploads',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Delimiter': {
          'location': 'urlPath',
          'sentAs': 'delimiter'
        },
        'KeyMarker': {
          'location': 'urlPath',
          'sentAs': 'key-marker'
        },
        'MaxUploads': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'max-uploads'
        },
        'Prefix': {
          'location': 'urlPath',
          'sentAs': 'prefix'
        },
        'UploadIdMarker': {
          'location': 'urlPath',
          'sentAs': 'upload-id-marker'
        },
        'EncodingType': {
          'location': 'urlPath',
          'sentAs': 'encoding-type'
        }
      }
    },
    'ListMultipartUploadsOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ListMultipartUploadsResult'
      },
      'parameters': {
        'Bucket': {
          'location': 'xml',
          'sentAs': 'Bucket'
        },
        'KeyMarker': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'KeyMarker'
        },
        'UploadIdMarker': {
          'location': 'xml',
          'sentAs': 'UploadIdMarker'
        },
        'NextKeyMarker': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'NextKeyMarker'
        },
        'Prefix': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Prefix'
        },
        'Delimiter': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Delimiter'
        },
        'NextUploadIdMarker': {
          'location': 'xml',
          'sentAs': 'NextUploadIdMarker'
        },
        'MaxUploads': {
          'location': 'xml',
          'sentAs': 'MaxUploads'
        },
        'IsTruncated': {
          'location': 'xml',
          'sentAs': 'IsTruncated'
        },
        'EncodingType': {
          'location': 'xml',
          'sentAs': 'EncodingType'
        },
        'Uploads': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Upload',
          'items': {
            'type': 'object',
            'parameters': {
              'UploadId': {
                'sentAs': 'UploadId'
              },
              'Key': {
                'decode': true,
                'sentAs': 'Key'
              },
              'Initiated': {
                'sentAs': 'Initiated'
              },
              'StorageClass': {
                'sentAs': 'StorageClass'
              },
              'Owner': owner,
              'Initiator': initiator
            }
          }
        },
        'CommonPrefixes': commonPrefixes
      }
    },
    'UploadPart': {
      'httpMethod': 'PUT',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'PartNumber': {
          'required': true,
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'partNumber'
        },
        'UploadId': {
          'required': true,
          'location': 'urlPath',
          'sentAs': 'uploadId'
        },
        'ContentMD5': {
          'location': 'header',
          'sentAs': 'Content-MD5'
        },
        'Body': {
          'location': 'body'
        },
        'SourceFile': {
          'type': 'srcFile'
        },
        'Offset': {
          'type': 'plain'
        },
        'PartSize': {
          'type': 'plain'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseKmsProjectId': {
          'location': 'header',
          'sentAs': 'sse-kms-key-project-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        },
        'ProgressCallback': {
          'type': 'plain'
        }
      }
    },
    'UploadPartOutput': {
      'parameters': {
        'ETag': {
          'location': 'header',
          'sentAs': 'etag'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseKmsProjectId': {
          'location': 'header',
          'sentAs': 'sse-kms-key-project-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        }
      }
    },
    'ListParts': {
      'httpMethod': 'GET',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'UploadId': {
          'required': true,
          'location': 'urlPath',
          'sentAs': 'uploadId'
        },
        'MaxParts': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'max-parts'
        },
        'PartNumberMarker': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'part-number-marker'
        },
        'EncodingType': {
          'location': 'urlPath',
          'sentAs': 'encoding-type'
        }
      }
    },
    'ListPartsOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ListPartsResult'
      },
      'parameters': {
        'Bucket': {
          'location': 'xml',
          'sentAs': 'Bucket'
        },
        'Key': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Key'
        },
        'UploadId': {
          'location': 'xml',
          'sentAs': 'UploadId'
        },
        'PartNumberMarker': {
          'location': 'xml',
          'sentAs': 'PartNumberMarker'
        },
        'NextPartNumberMarker': {
          'location': 'xml',
          'sentAs': 'NextPartNumberMarker'
        },
        'MaxParts': {
          'location': 'xml',
          'sentAs': 'MaxParts'
        },
        'IsTruncated': {
          'location': 'xml',
          'sentAs': 'IsTruncated'
        },
        'StorageClass': {
          'location': 'xml',
          'sentAs': 'StorageClass'
        },
        'EncodingType': {
          'location': 'urlPath',
          'sentAs': 'EncodingType'
        },
        'Initiator': initiator,
        'Owner': owner,
        'Parts': {
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Part',
          'items': {
            'type': 'object',
            'parameters': {
              'PartNumber': {
                'sentAs': 'PartNumber'
              },
              'LastModified': {
                'sentAs': 'LastModified'
              },
              'ETag': {
                'sentAs': 'ETag'
              },
              'Size': {
                'sentAs': 'Size'
              }
            }
          }
        }
      }
    },
    'CopyPart': {
      'httpMethod': 'PUT',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'PartNumber': {
          'required': true,
          'location': 'urlPath',
          'sentAs': 'partNumber',
          'type': 'number'
        },
        'UploadId': {
          'required': true,
          'location': 'urlPath',
          'sentAs': 'uploadId'
        },
        'CopySource': {
          'required': true,
          'location': 'header',
          'sentAs': 'copy-source',
          'skipEncoding': true,
          'withPrefix': true
        },
        'CopySourceRange': {
          'location': 'header',
          'sentAs': 'copy-source-range',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        },
        'CopySourceSseC': {
          'location': 'header',
          'sentAs': 'copy-source-server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'CopySourceSseCKey': {
          'location': 'header',
          'sentAs': 'copy-source-server-side-encryption-customer-key',
          'type': 'password',
          'withPrefix': true
        }
      }
    },
    'CopyPartOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'CopyPartResult'
      },
      'parameters': {
        'LastModified': {
          'location': 'xml',
          'sentAs': 'LastModified'
        },
        'ETag': {
          'location': 'xml',
          'sentAs': 'ETag'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        }
      }
    },
    'AbortMultipartUpload': {
      'httpMethod': 'DELETE',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'UploadId': {
          'required': true,
          'location': 'urlPath',
          'sentAs': 'uploadId'
        }
      }
    },

    'CompleteMultipartUpload': {
      'httpMethod': 'POST',
      'data': {
        'xmlRoot': 'CompleteMultipartUpload'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'UploadId': {
          'required': true,
          'location': 'urlPath',
          'sentAs': 'uploadId'
        },
        'EncodingType': {
          'location': 'urlPath',
          'sentAs': 'encoding-type'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseKmsProjectId': {
          'location': 'header',
          'sentAs': 'sse-kms-key-project-id',
          'withPrefix': true
        },
        'Parts': {
          'required': true,
          'type': 'array',
          'location': 'xml',
          'sentAs': 'Part',
          'items': {
            'type': 'object',
            'parameters': {
              'PartNumber': {
                'sentAs': 'PartNumber'
              },
              'ETag': {
                'sentAs': 'ETag'
              }
            }
          }
        }
      }
    },
    'CompleteMultipartUploadOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'CompleteMultipartUploadResult'
      },
      'parameters': {
        'VersionId': {
          'location': 'header',
          'sentAs': 'version-id',
          'withPrefix': true
        },
        'Location': {
          'location': 'xml',
          'sentAs': 'Location'
        },
        'EncodingType': {
          'location': 'xml',
          'sentAs': 'EncodingType'
        },
        'Bucket': {
          'location': 'xml',
          'sentAs': 'Bucket'
        },
        'Key': {
          'decode': true,
          'location': 'xml',
          'sentAs': 'Key'
        },
        'ETag': {
          'location': 'xml',
          'sentAs': 'ETag'
        },
        'SseKms': {
          'location': 'header',
          'sentAs': 'server-side-encryption',
          'withPrefix': true
        },
        'SseKmsKey': {
          'location': 'header',
          'sentAs': 'server-side-encryption-kms-key-id',
          'withPrefix': true
        },
        'SseKmsProjectId': {
          'location': 'header',
          'sentAs': 'sse-kms-key-project-id',
          'withPrefix': true
        },
        'SseC': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-algorithm',
          'withPrefix': true
        },
        'SseCKeyMd5': {
          'location': 'header',
          'sentAs': 'server-side-encryption-customer-key-MD5',
          'withPrefix': true
        }
      }
    },
    'OptionsBucket': {
      'httpMethod': 'OPTIONS',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Origin': {
          'required': true,
          'location': 'header',
          'sentAs': 'Origin'
        },
        'AccessControlRequestMethods': {
          'required': true,
          'type': 'array',
          'location': 'header',
          'sentAs': 'Access-Control-Request-Method',
          'items': {
            'type': 'string'
          }
        },
        'AccessControlRequestHeaders': {
          'type': 'array',
          'location': 'header',
          'sentAs': 'Access-Control-Request-Headers',
          'items': {
            'type': 'string'
          }
        }
      }
    },
    'OptionsBucketOutput': {
      'parameters': {
        'AllowOrigin': {
          'location': 'header',
          'sentAs': 'access-control-allow-origin'
        },
        'AllowHeader': {
          'location': 'header',
          'sentAs': 'access-control-allow-headers'
        },
        'AllowMethod': {
          'location': 'header',
          'sentAs': 'access-control-allow-methods'
        },
        'ExposeHeader': {
          'location': 'header',
          'sentAs': 'access-control-expose-headers'
        },
        'MaxAgeSeconds': {
          'location': 'header',
          'sentAs': 'access-control-max-age'
        }
      }
    },
    'OptionsObject': {
      'httpMethod': 'OPTIONS',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Key': {
          'required': true,
          'location': 'uri'
        },
        'Origin': {
          'required': true,
          'location': 'header',
          'sentAs': 'Origin'
        },
        'AccessControlRequestMethods': {
          'required': true,
          'type': 'array',
          'location': 'header',
          'sentAs': 'Access-Control-Request-Method',
          'items': {
            'type': 'string'
          }
        },
        'AccessControlRequestHeaders': {
          'type': 'array',
          'location': 'header',
          'sentAs': 'Access-Control-Request-Headers',
          'items': {
            'type': 'string'
          }
        }
      }
    },
    'OptionsObjectOutput': {
      'parameters': {
        'AllowOrigin': {
          'location': 'header',
          'sentAs': 'access-control-allow-origin'
        },
        'AllowHeader': {
          'location': 'header',
          'sentAs': 'access-control-allow-headers'
        },
        'AllowMethod': {
          'location': 'header',
          'sentAs': 'access-control-allow-methods'
        },
        'ExposeHeader': {
          'location': 'header',
          'sentAs': 'access-control-expose-headers'
        },
        'MaxAgeSeconds': {
          'location': 'header',
          'sentAs': 'access-control-max-age'
        }
      }
    },
    'GetBucketEncryption': {
      'httpMethod': 'GET',
      'urlPath': 'encryption',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketEncryptionOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ServerSideEncryptionConfiguration'
      },
      'parameters': {
        'Rule': {
          'type': 'object',
          'location': 'xml',
          'sentAs': 'Rule',

          'parameters': {
            'ApplyServerSideEncryptionByDefault': {
              'type': 'object',
              'sentAs': 'ApplyServerSideEncryptionByDefault',
              'parameters': {
                'SSEAlgorithm': {
                  'sentAs': 'SSEAlgorithm'
                },
                'KMSMasterKeyID': {
                  'sentAs': 'KMSMasterKeyID'
                },
                'ProjectID': {
                  'sentAs': 'ProjectID'
                }
              }
            }
          }
        }
      }
    },
    'SetBucketEncryption': {
      'httpMethod': 'PUT',
      'urlPath': 'encryption',
      'data': {
        'xmlRoot': 'ServerSideEncryptionConfiguration'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Rule': bucketEncryptionRule
      }
    },
    'SetBucketEncryptionOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ServerSideEncryptionConfiguration'
      },
      'parameters': {
        'Rule': bucketEncryptionRule
      }
    },
    'DeleteBucketEncryption': {
      'httpMethod': 'DELETE',
      'urlPath': 'encryption',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'DeleteBucketEncryptionOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ServerSideEncryptionConfiguration'
      },
      'parameters': {
        'Rule': bucketEncryptionRule
      }
    },
    'GetBucketRequesterPay': {
      'httpMethod': 'GET',
      'urlPath': 'requestPayment',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketRequesterPayOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'RequestPaymentConfiguration'
      },
      'parameters': {
        'Payer': {
          'location': 'xml',
          'sentAs': 'Payer'
        }
      }
    },
    'SetBucketRequesterPay': {
      'httpMethod': 'PUT',
      'urlPath': 'requestPayment',
      'data': {
        'xmlRoot': 'RequestPaymentConfiguration'
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Payer': {
          'location': 'xml',
          'sentAs': 'Payer'
        }
      }
    },
    'SetBucketRequesterPayOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'RequestPaymentConfiguration'
      },
      'parameters': {
        'Payer': {
          'location': 'xml',
          'sentAs': 'Payer'
        }
      }
    },

    'SetMirrorBackToSource': {
      'httpMethod': 'PUT',
      'urlPath': 'mirrorBackToSource',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        },
        'Rules': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'SetMirrorBackToSourceOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'Rules': {
          'location': 'body'
        }
      }
    },
    'GetMirrorBackToSource': {
      'httpMethod': 'GET',
      'urlPath': 'mirrorBackToSource',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        }
      }
    },
    'GetMirrorBackToSourceOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'Rules': {
          'location': 'body'
        }
      }
    },
    'DeleteMirrorBackToSource': {
      'httpMethod': 'DELETE',
      'urlPath': 'mirrorBackToSource',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        }
      }
    },
    'GetBucketDirectColdAccess': {
      'httpMethod': 'GET',
      'urlPath': 'directcoldaccess',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketDirectColdAccessOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'DirectColdAccessConfiguration'
      },
      'parameters': {
        'Status': {
          'location': 'xml',
          'sentAs': 'Status'
        }
      }
    },
    'SetBucketDirectColdAccess': {
      'httpMethod': 'PUT',
      'urlPath': 'directcoldaccess',
      'data': {
        'xmlRoot': 'DirectColdAccessConfiguration',
        'md5': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Status': {
          'required': true,
          'location': 'xml',
          'sentAs': 'Status'
        }
      }
    },

    'SetBucketDirectColdAccessOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'DirectColdAccessConfiguration'
      },
      'parameters': {
        'Status': {
          'location': 'xml',
          'sentAs': 'Status'
        }
      }
    },

    'DeleteBucketDirectColdAccess': {
      'httpMethod': 'DELETE',
      'urlPath': 'directcoldaccess',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },

    'DeleteBucketDirectColdAccessOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'DirectColdAccessConfiguration'
      },
      'parameters': {
        'Status': {
          'location': 'xml',
          'sentAs': 'Status'
        }
      }
    },
    'GetBucketCustomDomain': {
      'httpMethod': 'GET',
      'urlPath': 'customdomain',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetBucketCustomDomainOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'ListBucketCustomDomainsResult'
      },
      'parameters': {
        'Domains': {
          'location': 'xml',
          'type': 'array',
          'sentAs': 'Domains',
          'items': {
            'type': 'object',
            'parameters': {
              'DomainName': {
                'sentAs': 'DomainName'
              },
              'Value': {
                'sentAs': 'CreateTime'
              }
            }
          }
        }
      }
    },
    'SetBucketCustomDomain': {
      'httpMethod': 'PUT',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'DomainName': {
          'location': 'urlPath',
          'sentAs': 'customdomain'
        }
      }
    },
    'DeleteBucketCustomDomain': {
      'httpMethod': 'DELETE',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'DomainName': {
          'location': 'urlPath',
          'sentAs': 'customdomain'
        }
      }
    },
    'GetCDNNotifyConfiguration': {
      'httpMethod': 'GET',
      'urlPath': 'CDNNotifyConfiguration',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetCDNNotifyConfigurationOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'CDNNotifyConfiguration'
      },
      'parameters': {
        'Domain': {
          'location': 'xml',
          'type': 'array',
          'sentAs': 'Domain',
          'items': {
            'type': 'object',
            'parameters': {
              'Name': {
                'sentAs': 'Name'
              },
              'Events': {
                'type': 'array',
                'items': {
                  'type': 'adapter'
                },
                'sentAs': 'Event'
              }
            }
          }
        }
      }
    },
    'SetCdnNotifyConfiguration': {
      'httpMethod': 'PUT',
      'urlPath': 'CDNNotifyConfiguration',
      'data': {
        'xmlRoot': 'CDNNotifyConfiguration',
        'xmlAllowEmpty': true
      },
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'

        },
        'Domain': CDNNotifyConfiguration
      }
    },
    'GetQuota': {
      'httpMethod': 'GET',
      'urlPath': 'quota'
    },
    'GetQuotaOutput': {
      'data': {
        'type': 'xml',
        'xmlRoot': 'MaxBucketNumber'
      },
      'parameters': {
        'Size': {
          'location': 'xml',
          'sentAs': 'Number'
        }
      }
    },

    'GetWorkflowTrigger': {
      'httpMethod': 'GET',
      'urlPath': 'obsworkflowtriggerpolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        }
      }
    },
    'GetWorkflowTriggerOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'rules': {
          'location': 'body'
        }
      }
    },
    'DeleteWorkflowTrigger': {
      'httpMethod': 'DELETE',
      'urlPath': 'obsworkflowtriggerpolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        }
      }
    },
    'CreateWorkflowTrigger': {
      'httpMethod': 'PUT',
      'urlPath': 'obsworkflowtriggerpolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'ApiPath': {
          'location': 'uri'
        },
        'Rule': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'RestoreFailedWorkflowExecution': {
      'httpMethod': 'PUT',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'required': true,
          'location': 'uri',
          'sentAs': 'execution_name'
        },
        'GraphName': {
          'required': true,
          'location': 'urlPath',
          'sentAs': 'x-workflow-graph-name'
        }
      }
    },
    'CreateTemplate': {
      'httpMethod': 'POST',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Template': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'CreateWorkflow': {
      'httpMethod': 'POST',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'required': true,
          'location': 'uri',
          'sentAs': 'graph_name'
        },
        'Workflow_create': {
          'location': 'urlPath',
          'sentAs': 'x-workflow-create'
        },
        'Workflow': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'DeleteWorkflow': {
      'httpMethod': 'DELETE',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'location': 'uri',
          'sentAs': 'graph_name'
        }
      }
    },
    'UpdateWorkflow': {
      'httpMethod': 'PUT',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'location': 'uri',
          'sentAs': 'graph_name'
        },
        'Graph_name': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'GetWorkflowList': {
      'httpMethod': 'GET',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'location': 'uri',
          'sentAs': 'graph_name_prefix'
        },
        'XObsLimit': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'x-workflow-limit'
        },
        'XObsPrefix': {
          'location': 'urlPath',
          'sentAs': 'x-workflow-prefix'
        },
        'XObsStart': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'x-workflow-start'
        }
      }
    },
    'GetWorkflowListOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'workflows': {
          'location': 'body'
        }
      }
    },
    'GetWorkflowTemplateList': {
      'httpMethod': 'GET',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'location': 'uri',
          'sentAs': 'template_name_prefix'
        },
        'Start': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'x-workflow-start'
        },
        'Limit': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'x-workflow-limit'
        },
        'X-workflow-prefix': {
          'location': 'urlPath',
          'sentAs': 'x-workflow-prefix'
        }
      }
    },
    'GetWorkflowTemplateListOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'templates': {
          'location': 'body'
        }
      }
    },
    'GetWorkflowInstanceList': {
      'httpMethod': 'GET',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'location': 'uri',
          'sentAs': 'execution_name_prefix'
        },
        'Start': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'x-workflow-start'
        },
        'Limit': {
          'type': 'number',
          'location': 'urlPath',
          'sentAs': 'x-workflow-limit'
        },
        'Graph_name': {
          'location': 'urlPath',
          'sentAs': 'x-workflow-graph-name'
        },
        'State': {
          'location': 'urlPath',
          'sentAs': 'x-workflow-execution-state'
        },
        'X-workflow-prefix': {
          'location': 'urlPath',
          'sentAs': 'x-workflow-prefix'
        }
      }
    },
    'GetWorkflowInstanceListOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'instances': {
          'location': 'body'
        }
      }
    },
    'DeleteTemplate': {
      'httpMethod': 'DELETE',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'location': 'uri',
          'sentAs': 'template_name'
        }
      }
    },
    'GetActionTemplates': {
      'httpMethod': 'GET',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        },
        'Other_parameter': {
          'location': 'uri',
          'sentAs': 'template_name_prefix'
        },
        'XObsPrefix': {
          'location': 'urlPath',
          'sentAs': 'x-workflow-prefix'
        },
        'XObsCategory': {
          'type': 'String',
          'location': 'urlPath',
          'sentAs': 'x-workflow-category'
        }
      }
    },
    'GetActionTemplatesOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'actions': {
          'location': 'body'
        }
      }
    },
    'GetWorkflowAuthorization': {
      'httpMethod': 'GET',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        }
      }

    },
    'GetWorkflowAuthorizationOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'authorization': {
          'location': 'body'
        }
      }
    },
    'OpenWorkflowAuthorization': {
      'httpMethod': 'POST',
      'parameters': {
        'ApiPath': {
          'location': 'uri'
        }
      }
    },

    'CreateOnlineDecom': {
      'httpMethod': 'PUT',
      'urlPath': 'obscompresspolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        },
        'Decom': {
          'required': true,
          'location': 'body'
        }
      }
    },
    'GetOnlineDecom': {
      'httpMethod': 'GET',
      'urlPath': 'obscompresspolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    },
    'GetOnlineDecomOutput': {
      'data': {
        'type': 'body'
      },
      'parameters': {
        'Decom': {
          'location': 'body'
        }
      }
    },
    'DeleteOnlineDecom': {
      'httpMethod': 'DELETE',
      'urlPath': 'obscompresspolicy',
      'parameters': {
        'Bucket': {
          'required': true,
          'location': 'uri'
        }
      }
    }
  }

  return operations
});
/**
 * Copyright 2019 Huawei Technologies Co.,Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
 * this file except in compliance with the License.  You may obtain a copy of the
 * License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 */
(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    define('xml2js', [], factory)
  } else {
    root['xml2js'] = factory()
  }
})(undefined || window, function() {
  function Xml2Json() {
    var json2Str = function json2Str(jsonObj) {
      var rejsn = JSON.stringify(jsonObj, undefined, 2).replace(/(\\t|\\r|\\n)/g, '').replace(/"",[\n\t\r\s]+""[,]*/g, '').replace(/(\n[\t\s\r]*\n)/g, '').replace(/[\s\t]{2,}""[,]{0,1}/g, '').replace(/"[\s\t]{1,}"[,]{0,1}/g, '')
      return rejsn.indexOf('"parsererror": {') === -1 ? rejsn : 'Invalid XML format'
    }

    var setJsonObj = function setJsonObj(xmlDoc) {
      var jsonObj = {}
      if (xmlDoc.nodeType === 1) {
        if (xmlDoc.attributes.length > 0) {
          jsonObj['@attributes'] = {}
          for (var j = 0; j < xmlDoc.attributes.length; j++) {
            var attribute = xmlDoc.attributes.item(j)
            jsonObj['@attributes'][attribute.nodeName] = attribute.value
          }
        }
      } else if (xmlDoc.nodeType === 3) {
        jsonObj = xmlDoc.nodeValue
      }
      if (xmlDoc.hasChildNodes()) {
        for (var i = 0; i < xmlDoc.childNodes.length; i++) {
          var item = xmlDoc.childNodes.item(i)
          var nodeName = item.nodeName
          if (jsonObj[nodeName] === undefined) {
            jsonObj[nodeName] = setJsonObj(item)
          } else {
            if (jsonObj[nodeName].push === undefined) {
              var old = jsonObj[nodeName]
              jsonObj[nodeName] = []
              jsonObj[nodeName].push(old)
            }
            jsonObj[nodeName].push(setJsonObj(item))
          }
        }
      }
      return jsonObj
    }

    var self = this
    self.parseString = function(xml, rstr) {
      var xmlDoc = void 0
      if (window.DOMParser) {
        xmlDoc = new window.DOMParser().parseFromString(xml, 'text/xml')
      } else {
        xmlDoc = new window.ActiveXObject('Microsoft.XMLDOM')
        xmlDoc.async = 'false'
      }
      var ret = json2Str(setJsonObj(xmlDoc))
      return rstr === undefined ? JSON.parse(ret) : ret
    }
  }

  return new Xml2Json()
});

/**
 * Copyright 2019 Huawei Technologies Co.,Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
 * this file except in compliance with the License.  You may obtain a copy of the
 * License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 */
(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    define('utils', ['URI', 'axios', 'jsSHA', 'Base64', 'md5', 'xml2js', 'obsModel', 'v2Model'], factory)
  } else {
    root['utils'] = factory(root['URI'], root['axios'], root['jsSHA'], root['Base64'], root['md5'], root['xml2js'], root['obsModel'], root['v2Model'])
  }
})(undefined || window, function(URI, axios, SHA, Base64, md5, xml2js, obsModel, v2Model) {
  var crypto = {
    createHmac: function createHmac(algorithm, key) {
      var algorithmKey = void 0
      if (algorithm === 'sha1') {
        algorithmKey = 'SHA-1'
      } else if (algorithm === 'sha512') {
        algorithmKey = 'SHA-512'
      } else {
        algorithmKey = 'SHA-256'
      }
      var shaObj = new SHA(algorithmKey, 'TEXT')
      shaObj.setHMACKey(key, key instanceof ArrayBuffer ? 'ARRAYBUFFER' : 'TEXT')
      return {
        update: function update(message) {
          shaObj.update(message)
          return this
        },

        digest: function digest(type) {
          if (type === 'hex') {
            return shaObj.getHMAC('HEX')
          }
          if (type === 'base64') {
            return shaObj.getHMAC('B64')
          }
          return shaObj.getHMAC('ARRAYBUFFER')
        }
      }
    },

    createHash: function createHash(algorithm) {
      if (algorithm === 'md5') {
        return {
          update: function update(message) {
            if (!this.message) {
              this.message = message
            } else {
              this.message += message
            }
            return this
          },

          digest: function digest(type) {
            if (type === 'hex') {
              return md5.MD5(this.message)
            }
            if (type === 'base64') {
              var encodeFunc = window.btoa ? window.btoa : Base64.encode
              return encodeFunc(md5.MD5(this.message, false, true))
            }
            if (type === 'rawbase64') {
              var _encodeFunc = window.btoa ? window.btoa : Base64.encode
              return _encodeFunc(md5.RawMD5(this.message, false, true))
            }
            return md5.MD5(this.message, false, true)
          }
        }
      }

      var algorithmKey = void 0
      if (algorithm === 'sha1') {
        algorithmKey = 'SHA-1'
      } else if (algorithm === 'sha512') {
        algorithmKey = 'SHA-512'
      } else {
        algorithmKey = 'SHA-256'
      }
      var shaObj = new SHA(algorithmKey, 'TEXT')

      return {
        update: function update(message) {
          shaObj.update(message)
          return this
        },

        digest: function digest(type) {
          if (type === 'hex') {
            return shaObj.getHash('HEX')
          }
          if (type === 'base64') {
            return shaObj.getHash('B64')
          }
          return shaObj.getHash('ARRAYBUFFER')
        }
      }
    }
  }

  var urlLib = {
    parse: function parse(url) {
      var uri = URI.parse(url)
      return {
        hostname: uri.hostname,

        port: uri.port,

        host: uri.hostname,

        protocol: uri.protocol ? uri.protocol + ':' : '',

        query: uri.query,

        path: uri.path + (uri.query ? '?' + uri.query : ''),

        pathname: uri.path,

        search: uri.query ? '?' + uri.query : ''
      }
    }
  }

  var CONTENT_SHA256 = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
  var OBS_SDK_VERSION = '3.20.1'

  var mimeTypes = {
    '7z': 'application/x-7z-compressed',
    'aac': 'audio/x-aac',
    'ai': 'application/postscript',
    'aif': 'audio/x-aiff',
    'asc': 'text/plain',
    'asf': 'video/x-ms-asf',
    'atom': 'application/atom+xml',
    'avi': 'video/x-msvideo',
    'bmp': 'image/bmp',
    'bz2': 'application/x-bzip2',
    'cer': 'application/pkix-cert',
    'crl': 'application/pkix-crl',
    'crt': 'application/x-x509-ca-cert',
    'css': 'text/css',
    'csv': 'text/csv',
    'cu': 'application/cu-seeme',
    'deb': 'application/x-debian-package',
    'doc': 'application/msword',
    'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    'dvi': 'application/x-dvi',
    'eot': 'application/vnd.ms-fontobject',
    'eps': 'application/postscript',
    'epub': 'application/epub+zip',
    'etx': 'text/x-setext',
    'flac': 'audio/flac',
    'flv': 'video/x-flv',
    'gif': 'image/gif',
    'gz': 'application/gzip',
    'htm': 'text/html',
    'html': 'text/html',
    'ico': 'image/x-icon',
    'ics': 'text/calendar',
    'ini': 'text/plain',
    'iso': 'application/x-iso9660-image',
    'jar': 'application/java-archive',
    'jpe': 'image/jpeg',
    'jpeg': 'image/jpeg',
    'jpg': 'image/jpeg',
    'js': 'text/javascript',
    'json': 'application/json',
    'latex': 'application/x-latex',
    'log': 'text/plain',
    'm4a': 'audio/mp4',
    'm4v': 'video/mp4',
    'mid': 'audio/midi',
    'midi': 'audio/midi',
    'mov': 'video/quicktime',
    'mp3': 'audio/mpeg',
    'mp4': 'video/mp4',
    'mp4a': 'audio/mp4',
    'mp4v': 'video/mp4',
    'mpe': 'video/mpeg',
    'mpeg': 'video/mpeg',
    'mpg': 'video/mpeg',
    'mpg4': 'video/mp4',
    'oga': 'audio/ogg',
    'ogg': 'audio/ogg',
    'ogv': 'video/ogg',
    'ogx': 'application/ogg',
    'pbm': 'image/x-portable-bitmap',
    'pdf': 'application/pdf',
    'pgm': 'image/x-portable-graymap',
    'png': 'image/png',
    'pnm': 'image/x-portable-anymap',
    'ppm': 'image/x-portable-pixmap',
    'ppt': 'application/vnd.ms-powerpoint',
    'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
    'ps': 'application/postscript',
    'qt': 'video/quicktime',
    'rar': 'application/x-rar-compressed',
    'ras': 'image/x-cmu-raster',
    'rss': 'application/rss+xml',
    'rtf': 'application/rtf',
    'sgm': 'text/sgml',
    'sgml': 'text/sgml',
    'svg': 'image/svg+xml',
    'swf': 'application/x-shockwave-flash',
    'tar': 'application/x-tar',
    'tif': 'image/tiff',
    'tiff': 'image/tiff',
    'torrent': 'application/x-bittorrent',
    'ttf': 'application/x-font-ttf',
    'txt': 'text/plain',
    'wav': 'audio/x-wav',
    'webm': 'video/webm',
    'wma': 'audio/x-ms-wma',
    'wmv': 'video/x-ms-wmv',
    'woff': 'application/x-font-woff',
    'wsdl': 'application/wsdl+xml',
    'xbm': 'image/x-xbitmap',
    'xls': 'application/vnd.ms-excel',
    'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    'xml': 'application/xml',
    'xpm': 'image/x-xpixmap',
    'xwd': 'image/x-xwindowdump',
    'yaml': 'text/yaml',
    'yml': 'text/yaml',
    'zip': 'application/zip'
  }

  var allowedResourceParameterNames = ['inventory', 'acl', 'backtosource', 'policy', 'torrent', 'logging', 'location', 'storageinfo', 'quota', 'storageclass', 'storagepolicy', 'mirrorbacktosource', 'requestpayment', 'versions', 'versioning', 'versionid', 'uploads', 'uploadid', 'partnumber', 'website', 'notification', 'replication', 'lifecycle', 'deletebucket', 'delete', 'cors', 'restore', 'tagging', 'append', 'position', 'response-content-type', 'response-content-language', 'response-expires', 'response-cache-control', 'response-content-disposition', 'response-content-encoding', 'x-image-process', 'x-oss-process', 'encryption', 'obsworkflowtriggerpolicy', 'x-workflow-limit', 'x-workflow-prefix', 'x-workflow-start', 'x-workflow-template-name', 'x-workflow-graph-name', 'x-workflow-execution-state', 'x-workflow-category', 'x-workflow-prefix', 'x-workflow-create', 'directcoldaccess', 'customdomain', 'cdnnotifyconfiguration', 'metadata', 'dispolicy', 'obscompresspolicy', 'sfsacl']

  var allowedResponseHttpHeaderMetadataNames = ['content-type', 'content-md5', 'content-length', 'content-language', 'expires', 'origin', 'cache-control', 'content-disposition', 'content-encoding', 'x-default-storage-class', 'location', 'date', 'etag', 'host', 'last-modified', 'content-range', 'x-reserved', 'access-control-allow-origin', 'access-control-allow-headers', 'access-control-max-age', 'access-control-allow-methods', 'access-control-expose-headers', 'connection', 'x-obs-location-clustergroup-id']

  var commonHeaders = {
    'content-length': 'ContentLength',
    'date': 'Date',
    'x-reserved': 'Reserved'
  }

  var obsAllowedStorageClass = ['STANDARD', 'WARM', 'COLD']

  var v2AllowedStorageClass = ['STANDARD', 'STANDARD_IA', 'GLACIER']

  var obsAllowedAcl = ['private', 'public-read', 'public-read-write', 'public-read-delivered', 'public-read-write-delivered']

  var v2AllowedAcl = ['private', 'public-read', 'public-read-write', 'authenticated-read', 'bucket-owner-read', 'bucket-owner-full-control', 'log-delivery-write']

  var obsAllowedUri = ['Everyone', 'LogDelivery']

  var v2AllowedUri = ['http://acs.amazonaws.com/groups/global/AllUsers', 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers', 'http://acs.amazonaws.com/groups/s3/LogDelivery']

  var obsAllowedEvent = ['ObjectCreated', 'ObjectRemoved', 'ObjectCreated:*', 'ObjectCreated:Put', 'ObjectCreated:Post', 'ObjectCreated:Copy', 'ObjectCreated:CompleteMultipartUpload', 'ObjectRemoved:*', 'ObjectRemoved:Delete', 'ObjectRemoved:DeleteMarkerCreated']
  var v2AllowedEvent = ['ObjectCreated', 'ObjectRemoved', 's3:ObjectCreated:*', 's3:ObjectCreated:Put', 's3:ObjectCreated:Post', 's3:ObjectCreated:Copy', 's3:ObjectCreated:CompleteMultipartUpload', 's3:ObjectRemoved:*', 's3:ObjectRemoved:Delete', 's3:ObjectRemoved:DeleteMarkerCreated']

  var negotiateMethod = 'HeadApiVersion'

  var obsSignatureContext = {
    signature: 'obs',
    headerPrefix: 'x-obs-',
    headerMetaPrefix: 'x-obs-meta-',
    authPrefix: 'OBS'
  }

  var v2SignatureContext = {
    signature: 'v2',
    headerPrefix: 'x-amz-',
    headerMetaPrefix: 'x-amz-meta-',
    authPrefix: 'AWS'
  }

  function encodeURIWithSafe(str, safe, skipEncoding) {
    str = String(str)
    if (str.length === 0) {
      return ''
    }
    if (skipEncoding) {
      return str
    }
    var ret = void 0
    if (safe) {
      ret = []
      var _iteratorNormalCompletion = true
      var _didIteratorError = false
      var _iteratorError = undefined

      try {
        for (var _iterator = str[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
          var element = _step.value

          ret.push(safe.indexOf(element) >= 0 ? element : encodeURIComponent(element))
        }
      } catch (err) {
        _didIteratorError = true
        _iteratorError = err
      } finally {
        try {
          if (!_iteratorNormalCompletion && _iterator.return) {
            _iterator.return()
          }
        } finally {
          if (_didIteratorError) {
            throw _iteratorError
          }
        }
      }

      ret = ret.join('')
    } else {
      ret = encodeURIComponent(str)
    }
    return ret.replace(/!/g, '%21').replace(/\*/g, '%2A').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29')
  }

  function headerTostring(obj) {
    return JSON ? JSON.stringify(obj) : ''
  }

  function parseObjectFromHeaders(sentAs, headers) {
    var metadata = {}
    for (var key in headers) {
      if ({}.hasOwnProperty.call(headers, key)) {
        var k = String(key).toLowerCase()
        if (k.indexOf(sentAs) === 0) {
          metadata[k.slice(sentAs.length)] = headers[key]
        }
      }
    }
    return metadata
  }

  function isArray(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]'
  }

  function isFunction(obj) {
    return Object.prototype.toString.call(obj) === '[object Function]'
  }

  function isObject(obj) {
    return Object.prototype.toString.call(obj) === '[object Object]'
  }

  // function utcToLocaleString(utcDate){
  // 	return utcDate ? new Date(Date.parse(utcDate)).toLocaleString() : '';
  // }

  function makeObjFromXml(xml, bc) {
    if ((typeof xml === 'undefined' ? 'undefined' : _typeof(xml)) === 'object') {
      return bc(null, xml)
    }
    try {
      return bc(null, xml2js.parseString(xml))
    } catch (err) {
      return bc(err, null)
    }
  }

  function getExpireDate(utcDateStr) {
    var date = new Date(Date.parse(utcDateStr))
    var hour = date.getUTCHours()
    var min = date.getUTCMinutes()
    var sec = date.getUTCSeconds()
    var day = date.getUTCDate()
    var moth = date.getUTCMonth() + 1
    var year = date.getUTCFullYear()
    var expireDate = ''
    expireDate += year + '-'

    if (moth < 10) {
      expireDate += '0'
    }
    expireDate += moth + '-'

    if (day < 10) {
      expireDate += '0'
    }
    expireDate += day + 'T'

    if (hour < 10) {
      expireDate += '0'
    }
    expireDate += hour + ':'

    if (min < 10) {
      expireDate += '0'
    }
    expireDate += min + ':'

    if (sec < 10) {
      expireDate += '0'
    }
    expireDate += sec + 'Z'
    return expireDate
  }

  function getDates(utcDateStr) {
    var date = new Date(Date.parse(utcDateStr))
    var hour = date.getUTCHours()
    var min = date.getUTCMinutes()
    var sec = date.getUTCSeconds()
    var day = date.getUTCDate()
    var moth = date.getUTCMonth() + 1
    var year = date.getUTCFullYear()
    var shortDate = ''
    var longDate = ''
    shortDate += year

    if (moth < 10) {
      shortDate += '0'
    }
    shortDate += moth

    if (day < 10) {
      shortDate += '0'
    }
    shortDate += day

    longDate += shortDate + 'T'
    if (hour < 10) {
      longDate += '0'
    }
    longDate += hour

    if (min < 10) {
      longDate += '0'
    }
    longDate += min

    if (sec < 10) {
      longDate += '0'
    }
    longDate += sec + 'Z'
    return [shortDate, longDate]
  }

  function getSignedAndCanonicalHeaders(header) {
    var arrheadKey = []
    var arrhead = {}
    for (var key in header) {
      if ({}.hasOwnProperty.call(header, key)) {
        arrheadKey.push(key.toLowerCase())
        arrhead[key.toLowerCase()] = header[key]
      }
    }
    arrheadKey = arrheadKey.sort()
    var signedHeaders = ''
    var canonicalHeaders = ''
    for (var i = 0; i < arrheadKey.length; i++) {
      if (i !== 0) {
        signedHeaders += ';'
      }
      signedHeaders += arrheadKey[i]
      canonicalHeaders += arrheadKey[i] + ':' + arrhead[arrheadKey[i]] + '\n'
    }
    return [signedHeaders, canonicalHeaders]
  }

  function createV4Signature(shortDate, sk, region, stringToSign) {
    var dateKey = crypto.createHmac('sha256', 'AWS4' + sk).update(shortDate).digest()
    var dateRegionKey = crypto.createHmac('sha256', dateKey).update(region).digest()
    var dateRegionServiceKey = crypto.createHmac('sha256', dateRegionKey).update('s3').digest()
    var signingKey = crypto.createHmac('sha256', dateRegionServiceKey).update('aws4_request').digest()
    var signature = crypto.createHmac('sha256', signingKey).update(stringToSign).digest('hex')
    return signature
  }

  function getV4Signature(shortDate, longDate, sk, region, canonicalRequest) {
    var scop = shortDate + '/' + region + '/s3/aws4_request'
    var stringToSign = 'AWS4-HMAC-SHA256\n'
    stringToSign += longDate + '\n'
    stringToSign += scop + '\n'
    stringToSign += crypto.createHash('sha256').update(canonicalRequest).digest('hex')
    return createV4Signature(shortDate, sk, region, stringToSign)
  }

  function Utils(log_in) {
    this.log = log_in
    this.ak = null
    this.sk = null
    this.securityToken = null
    this.isSecure = true
    this.server = null
    this.pathStyle = false
    this.signatureContext = null
    this.isSignatureNegotiation = true
    this.bucketSignatureCache = {}
    this.region = 'region'
    this.port = null
    this.timeout = 300
    this.obsSdkVersion = OBS_SDK_VERSION
    this.isCname = false
    this.bucketEventEmitters = {}
    this.useRawXhr = false
  }

  Utils.prototype.encodeURIWithSafe = encodeURIWithSafe

  Utils.prototype.mimeTypes = mimeTypes

  Utils.prototype.refresh = function(ak, sk, securityToken) {
    this.ak = ak ? String(ak).trim() : null
    this.sk = sk ? String(sk).trim() : null
    this.securityToken = securityToken ? String(securityToken).trim() : null
  }

  Utils.prototype.initFactory = function(ak, sk, isSecure, server, pathStyle, signature, region, port, timeout, securityToken, isSignatureNegotiation, isCname, urlPrefix, regionDomains, setRequestHeaderHook, useRawXhr) {
    this.refresh(ak, sk, securityToken)

    this.urlPrefix = urlPrefix || ''
    this.regionDomains = regionDomains || null
    this.setRequestHeaderHook = setRequestHeaderHook || null
    if (!server) {
      throw new Error('Server is not set')
    }

    server = String(server).trim()

    if (server.indexOf('https://') === 0) {
      server = server.slice('https://'.length)
      isSecure = true
    } else if (server.indexOf('http://') === 0) {
      server = server.slice('http://'.length)
      isSecure = false
    }

    var index = server.lastIndexOf('/')
    while (index >= 0) {
      server = server.slice(0, index)
      index = server.lastIndexOf('/')
    }

    index = server.indexOf(':')
    if (index >= 0) {
      port = server.slice(index + 1)
      server = server.slice(0, index)
    }
    this.server = server

    if (/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/.test(this.server)) {
      pathStyle = true
    }

    if (isSecure !== undefined) {
      this.isSecure = isSecure
    }
    if (pathStyle !== undefined) {
      this.pathStyle = pathStyle
    }

    if (signature !== undefined) {
      signature = String(signature).trim().toLowerCase()
    } else {
      signature = 'obs'
    }

    if (isSignatureNegotiation !== undefined) {
      this.isSignatureNegotiation = isSignatureNegotiation
    }

    this.isCname = isCname

    if (this.pathStyle || this.isCname) {
      this.isSignatureNegotiation = false
      if (signature === 'obs') {
        signature = 'v2'
      }
    }

    this.signatureContext = signature === 'obs' ? obsSignatureContext : v2SignatureContext

    if (region !== undefined) {
      this.region = String(region)
    }

    this.port = port ? parseInt(port, 10) : this.isSecure ? 443 : 80

    if (timeout !== undefined) {
      this.timeout = parseInt(timeout, 10)
    }

    if (useRawXhr !== undefined) {
      this.useRawXhr = useRawXhr
    }
  }

  Utils.prototype.SseKmsAdapter = function(value, signatureContext) {
    value = value || ''
    value = String(value)
    var index = value.indexOf('aws:')
    if (signatureContext.signature === 'obs') {
      return index === 0 ? value.slice(4) : value
    }
    return index === 0 ? value : 'aws:' + value
  }

  Utils.prototype.BucketAdapter = function(value, signatureContext) {
    value = value || ''
    value = String(value)
    var index = value.indexOf('arn:aws:s3:::')
    if (signatureContext.signature === 'obs') {
      return index === 0 ? value.slice('arn:aws:s3:::'.length) : value
    }
    return index === 0 ? value : 'arn:aws:s3:::' + value
  }

  Utils.prototype.EventAdapter = function(value, signatureContext) {
    value = value || ''
    value = String(value)
    if (signatureContext.signature === 'obs') {
      if (obsAllowedEvent.indexOf(value) >= 0) {
        return value
      }
      if (v2AllowedEvent.indexOf(value) >= 0) {
        return value.substring(3)
      }
      return ''
    }
    if (v2AllowedEvent.indexOf(value) >= 0) {
      return value
    }
    if (obsAllowedEvent.indexOf(value) >= 0) {
      return 's3:' + value
    }
    return ''
  }

  Utils.prototype.URIAdapter = function(value, signatureContext) {
    value = value || ''
    value = String(value)
    if (signatureContext.signature === 'obs') {
      if (obsAllowedUri.indexOf(value) >= 0) {
        return value
      }
      if (value === 'AllUsers' || value === 'http://acs.amazonaws.com/groups/global/AllUsers') {
        return 'Everyone'
      }
      return ''
    }
    if (v2AllowedUri.indexOf(value) >= 0) {
      return value
    }
    if (value === 'Everyone' || value === 'AllUsers') {
      return 'http://acs.amazonaws.com/groups/global/AllUsers'
    }
    if (value === 'AuthenticatedUsers') {
      return 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers'
    }
    if (value === 'LogDelivery') {
      return 'http://acs.amazonaws.com/groups/s3/LogDelivery'
    }
    return ''
  }

  Utils.prototype.StorageClassAdapter = function(value, signatureContext) {
    value = value || ''
    value = String(value).toUpperCase()
    if (signatureContext.signature === 'obs') {
      if (obsAllowedStorageClass.indexOf(value) >= 0) {
        return value
      }
      if (value === 'STANDARD_IA') {
        return 'WARM'
      }
      if (value === 'GLACIER') {
        return 'COLD'
      }
      return ''
    }
    if (v2AllowedStorageClass.indexOf(value) >= 0) {
      return value
    }
    if (value === 'WARM') {
      return 'STANDARD_IA'
    }
    if (value === 'COLD') {
      return 'GLACIER'
    }
    return ''
  }

  Utils.prototype.ACLAdapter = function(value, signatureContext) {
    value = value || ''
    value = String(value).toLowerCase()
    if (signatureContext.signature === 'obs') {
      if (obsAllowedAcl.indexOf(value) >= 0) {
        return value
      }
      return ''
    }
    if (value === 'public-read-delivered') {
      value = 'public-read'
    } else if (value === 'public-read-write-delivered') {
      value = 'public-read-write'
    }

    if (v2AllowedAcl.indexOf(value) >= 0) {
      return value
    }
    return ''
  }

  Utils.prototype.doExec = function(funcName, param, callback) {
    var opt = this.makeParam(funcName, param)
    if ('err' in opt) {
      return callback(opt.err, null)
    }
    this.sendRequest(funcName, opt, callback)
  }

  Utils.prototype.doNegotiation = function(funcName, param, callback, checkBucket, checkCache, setCache) {
    var o = null
    var that = this
    if (checkCache && param.Bucket) {
      var item = this.bucketSignatureCache[param.Bucket]
      if (item && item.signatureContext && item.expireTime > new Date().getTime()) {
        param.signatureContext = item.signatureContext
        var opt = this.makeParam(funcName, param)
        if ('err' in opt) {
          return callback(opt.err, null)
        }
        opt.signatureContext = item.signatureContext
        return this.sendRequest(funcName, opt, callback)
      }

      o = this.bucketEventEmitters[param.Bucket]
      if (!o) {
        o = {
          s: 0,
          n: function n() {
            while (this.e && this.e.length > 0) {
              this.e.shift()()
            }
          }
        }
        this.bucketEventEmitters[param.Bucket] = o
      }

      if (o.s) {
        o.e.push(function() {
          that.doNegotiation(funcName, param, callback, checkBucket, checkCache, setCache)
        })
        return
      }

      o.e = []
      o.s = 1
    }

    this.doExec(negotiateMethod, checkBucket ? { Bucket: param.Bucket } : {}, function(err, result) {
      if (err) {
        callback(err, null)
        if (o) {
          o.s = 0
          o.n()
        }
        return
      }
      if (checkBucket && result.CommonMsg.Status === 404 || result.CommonMsg.Status >= 500) {
        callback(err, result)
        if (o) {
          o.s = 0
          o.n()
        }
        return
      }

      var signatureContext = v2SignatureContext
      if (result.CommonMsg.Status < 300 && result.InterfaceResult && result.InterfaceResult.ApiVersion >= '3.0') {
        signatureContext = obsSignatureContext
      }
      if (setCache) {
        that.bucketSignatureCache[param.Bucket] = {
          signatureContext: signatureContext,
          expireTime: new Date().getTime() + 15 + Math.ceil(Math.random() * 5) * 60 * 1000
        }
      }

      if (o) {
        o.s = 0
        o.n()
      }
      param.signatureContext = signatureContext
      var opt = that.makeParam(funcName, param)
      if ('err' in opt) {
        return callback(opt.err, null)
      }
      opt.signatureContext = signatureContext
      that.sendRequest(funcName, opt, callback)
    })
  }

  Utils.prototype.exec = function(funcName, param, callback) {
    var that = this
    if (that.isSignatureNegotiation && funcName !== negotiateMethod) {
      if (funcName === 'ListBuckets') {
        that.doNegotiation(funcName, param, callback, false, false, false)
      } else if (funcName === 'CreateBucket') {
        var _callback = function _callback(err, result) {
          if (!err && result.CommonMsg.Status === 400 && result.CommonMsg.Message === 'Unsupported Authorization Type' && param.signatureContext && param.signatureContext.signature === 'v2') {
            param.signatureContext = v2SignatureContext
            var opt = that.makeParam(funcName, param)
            if ('err' in opt) {
              return callback(opt.err, null)
            }
            opt.signatureContext = param.signatureContext
            that.sendRequest(funcName, opt, callback)
            return
          }
          callback(err, result)
        }

        that.doNegotiation(funcName, param, _callback, false, true, false)
      } else {
        that.doNegotiation(funcName, param, callback, true, true, true)
      }
      return
    }
    that.doExec(funcName, param, callback)
  }

  Utils.prototype.sliceBlob = function(blob, start, end, type) {
    type = type || blob.type
    if (blob.mozSlice) {
      return blob.mozSlice(start, end, type)
    }
    if (blob.webkitSlice) {
      return blob.webkitSlice(start, end, type)
    }
    return blob.slice(start, end, type)
  }

  Utils.prototype.toXml = function(mXml, xmlMeta, root, sentAs, signatureContext) {
    var xml = ''
    if (root !== null) {
      xml += this.buildXml(mXml, xmlMeta, root, sentAs, signatureContext)
      return xml
    }
    for (var key in xmlMeta) {
      if (key in mXml) {
        var _sentAs = xmlMeta[key].sentAs || key
        xml += this.buildXml(mXml, xmlMeta[key], key, _sentAs, signatureContext)
      }
    }
    return xml
  }

  Utils.prototype.buildXml = function(mXml, xmlMeta, key, sentAs, signatureContext) {
    var xml = ''
    var type = xmlMeta.type
    if (type === 'array') {
      for (var i = 0; i < mXml[key].length; i++) {
        if (xmlMeta.items.type === 'object') {
          if (!mXml[key][i]) {
            return xml
          }
          var result = this.toXml(mXml[key][i], xmlMeta.items.parameters, null, null, signatureContext)
          if (result !== '') {
            xml += '<' + sentAs + '>' + result + '</' + sentAs + '>'
          }
        } else if (xmlMeta.items.type === 'adapter') {
          xml += '<' + sentAs + '>' + String(this[key + 'Adapter'](mXml[key][i], signatureContext)).replace(/&/g, '&amp;').replace(/'/g, '&apos;').replace(/"/g, '&quot;') + '</' + sentAs + '>'
        } else if (xmlMeta.items.type !== 'array') {
          xml += '<' + sentAs + '>' + String(mXml[key][i]).replace(/&/g, '&amp;').replace(/'/g, '&apos;').replace(/"/g, '&quot;') + '</' + sentAs + '>'
        }
      }
    } else if (type === 'object') {
      if (!mXml[key]) {
        return xml
      }
      var _result = this.toXml(mXml[key], xmlMeta.parameters, null, null, signatureContext)
      if (_result !== '') {
        xml += '<' + sentAs
        if ('data' in xmlMeta) {
          if ('xsiNamespace' in xmlMeta.data) {
            xml += ' xmlns:xsi="' + xmlMeta.data.xsiNamespace + '"'
          }
          if ('xsiType' in xmlMeta.data) {
            xml += ' xsi:type="' + mXml[key][xmlMeta.data.xsiType] + '"'
          }
        }
        xml += '>'
        xml += _result + '</' + sentAs + '>'
      }
    } else if (type === 'adapter') {
      xml += '<' + sentAs + '>' + String(this[key + 'Adapter'](mXml[key], signatureContext)).replace(/&/g, '&amp;').replace(/'/g, '&apos;').replace(/"/g, '&quot;') + '</' + sentAs + '>'
    } else if (type !== 'ignore') {
      xml += '<' + sentAs + '>' + String(mXml[key]).replace(/&/g, '&amp;').replace(/'/g, '&apos;').replace(/"/g, '&quot;') + '</' + sentAs + '>'
    }
    if (xml && xmlMeta.wrapper) {
      var _wrapper = xmlMeta.wrapper
      xml = '<' + _wrapper + '>' + xml + '</' + _wrapper + '>'
    }
    return xml
  }

  Utils.prototype.jsonToObject = function(model, obj, root, ifRootXMlDecode) {
    var opt = {}
    if (root !== null) {
      this.buildObject(model, obj, root, opt, ifRootXMlDecode)
    } else {
      for (var key in model) {
        if ({}.hasOwnProperty.call(model, key)) {
          this.buildObject(model, obj, key, opt, ifRootXMlDecode)
        }
      }
    }
    return opt
  }

  Utils.prototype.buildObject = function(model, obj, key, opt, ifRootXMlDecode) {
    var setValue = function setValue(value) {
      return value && model[key].decode && ifRootXMlDecode ? decodeURIComponent(value.replace(/\+/g, '%20')) : value
    }

    if (isObject(obj)) {
      var flag = true
      var wrapper = model[key].wrapper
      if (wrapper && wrapper in obj) {
        obj = obj[wrapper]
        flag = isObject(obj)
      }
      if (flag) {
        var sentAs = model[key].sentAs || key
        if (sentAs in obj) {
          if (model[key].type === 'object') {
            opt[key] = this.jsonToObject(model[key].parameters, obj[sentAs], null, ifRootXMlDecode)
          } else if (model[key].type === 'array') {
            var arr = []
            if (!isArray(obj[sentAs])) {
              arr[0] = model[key].items.type === 'object' ? this.jsonToObject(model[key].items.parameters, obj[sentAs], null, ifRootXMlDecode) : setValue(obj[sentAs]['#text'] || '')
            } else {
              for (var i = 0; i < obj[sentAs].length; i++) {
                arr[i] = model[key].items.type === 'object' ? this.jsonToObject(model[key].items.parameters, obj[sentAs][i], null, ifRootXMlDecode) : setValue(obj[sentAs][i]['#text'])
              }
            }
            opt[key] = arr
          } else {
            opt[key] = setValue(obj[sentAs]['#text'])
          }
        }
      }
    }

    if (opt[key] === undefined) {
      if (model[key].type === 'object') {
        opt[key] = model[key].parameters ? this.jsonToObject(model[key].parameters, null, null, ifRootXMlDecode) : {}
      } else if (model[key].type === 'array') {
        opt[key] = []
      }
    }
  }

  Utils.prototype.makeParam = function(methodName, param) {
    var signatureContext = param.signatureContext || this.signatureContext
    var model = signatureContext.signature === 'obs' ? obsModel[methodName] : v2Model[methodName]
    var method = model.httpMethod
    var uri = '/'
    var urlPath = ''
    var xml = ''
    var exheaders = {}
    var opt = {}
    opt.$requestParam = param

    if ('urlPath' in model) {
      urlPath += '?'
      urlPath += model.urlPath
    }
    for (var key in model.parameters) {
      if ({}.hasOwnProperty.call(model.parameters, key)) {
        var meta = model.parameters[key]
        if (key === 'Bucket' && this.isCname) {
          continue
        }

        var _value = param[key]

        if (meta.required && (_value === null || _value === undefined || Object.prototype.toString.call(_value) === '[object String]' && _value === '')) {
          opt.err = key + ' is a required element!'
          this.log.runLog('error', methodName, opt.err)
          return opt
        }

        if (_value !== null && _value !== undefined) {
          if (meta.type === 'srcFile' || meta.type === 'dstFile') {
            opt[meta.type] = _value
            continue
          }

          if (meta.type === 'plain') {
            opt[key] = _value
          }

          var sentAs = meta.sentAs || key

          if (meta.withPrefix) {
            sentAs = signatureContext.headerPrefix + sentAs
          }

          if (meta.location === 'uri') {
            if (uri !== '/') {
              uri += '/'
            }
            uri += _value
          } else if (meta.location === 'header') {
            var safe = meta.encodingSafe || ' ;/?:@&=+$,'
            if (meta.type === 'object') {
              if (signatureContext.headerMetaPrefix === sentAs) {
                for (var item in _value) {
                  if ({}.hasOwnProperty.call(_value, item)) {
                    var value = _value[item]
                    item = String(item).trim().toLowerCase()
                    exheaders[item.indexOf(sentAs) === 0 ? item : sentAs + item] = encodeURIWithSafe(value, safe)
                  }
                }
              }
            } else if (meta.type === 'array') {
              var arr = []
              for (var _item in _value) {
                if ({}.hasOwnProperty.call(_value, _item)) {
                  arr[_item] = encodeURIWithSafe(_value[_item], safe)
                }
              }
              exheaders[sentAs] = arr
            } else if (meta.type === 'password') {
              var encodeFunc = window.btoa ? window.btoa : Base64.encode
              exheaders[sentAs] = encodeFunc(_value)
              var pwdSentAs = meta.pwdSentAs || sentAs + '-MD5'
              exheaders[pwdSentAs] = this.rawBufMD5(_value)
            } else if (meta.type === 'number' && Number(_value)) {
              exheaders[sentAs] = encodeURIWithSafe(String(_value), safe)
            } else if (meta.type === 'boolean') {
              exheaders[sentAs] = encodeURIWithSafe(_value ? 'true' : 'false', safe)
            } else if (meta.type === 'adapter') {
              var val = this[key + 'Adapter'](_value, signatureContext)
              if (val) {
                exheaders[sentAs] = encodeURIWithSafe(String(val), safe)
              }
            } else {
              exheaders[sentAs] = encodeURIWithSafe(String(_value), safe, meta.skipEncoding)
            }
          } else if (meta.location === 'urlPath') {
            var sep = urlPath === '' ? '?' : '&'
            var _value2 = _value
            if (meta.type !== 'number' || meta.type === 'number' && Number(_value2) >= 0) {
              urlPath += sep + encodeURIWithSafe(sentAs, '/') + '=' + encodeURIWithSafe(String(_value2), '/')
            }
          } else if (meta.location === 'xml') {
            var mxml = this.toXml(param, meta, key, sentAs, signatureContext)
            if (mxml) {
              xml += mxml
            }
          } else if (meta['location'] === 'body') {
            xml = _value
          }
        }
      }
    }

    var isFile = opt.dstFile === 'file'

    if (!('Content-Type' in exheaders) && !isFile) {
      exheaders['Content-Type'] = 'binary/octet-stream'
    }

    if ('data' in model && 'xmlRoot' in model.data) {
      if (xml || model.data.xmlAllowEmpty) {
        var xmlRoot = model.data.xmlRoot
        xml = '<' + xmlRoot + '>' + xml + '</' + xmlRoot + '>'
        exheaders['Content-Type'] = 'application/xml'
      }
    }
    if (isFile) {
      opt.rawUri = uri
    }

    exheaders.Host = this.server + (this.port === 80 || this.port === 443 ? '' : ':' + this.port)

    if (!this.pathStyle && !this.isCname) {
      var uriList = uri.split('/')
      if (uriList.length >= 2 && uriList[1]) {
        exheaders.Host = uriList[1] + '.' + exheaders.Host
        var requestUri = uri.replace(uriList[1], '')
        if (requestUri.indexOf('//') === 0) {
          requestUri = requestUri.slice(1)
        }
        if (signatureContext.signature === 'v4') {
          uri = requestUri
        } else if (requestUri === '/') {
          uri += '/'
        }
        opt.requestUri = encodeURIWithSafe(requestUri, '/')
      }
    }
    opt.method = method
    opt.uri = encodeURIWithSafe(uri, '/')
    opt.urlPath = urlPath
    if (xml) {
      if (model.data && model.data.md5) {
        exheaders['Content-MD5'] = this.bufMD5(xml)
        exheaders['Content-Length'] = xml.length === 0 ? '0' : String(xml.length)
      }
      opt.xml = xml
      this.log.runLog('debug', methodName, 'request content:' + xml)
    }

    opt.headers = exheaders

    if ('srcFile' in opt) {
      if (opt.srcFile instanceof window.File || opt.srcFile instanceof window.Blob) {
        var fileSize = opt.srcFile.size
        if ('Content-Length' in opt.headers || 'PartSize' in opt || 'Offset' in opt) {
          var offset = opt.Offset
          offset = offset && offset >= 0 && offset < fileSize ? offset : 0
          var partSize = void 0
          if ('PartSize' in opt) {
            partSize = opt.PartSize
          } else if ('Content-Length' in opt.headers) {
            partSize = parseInt(opt.headers['Content-Length'], 10)
          } else {
            partSize = fileSize
          }
          partSize = partSize && partSize > 0 && partSize <= fileSize - offset ? partSize : fileSize - offset
          opt.PartSize = partSize
          opt.Offset = offset
          opt.headers['Content-Length'] = String(opt.PartSize)
        }
      }
    }
    return opt
  }

  Utils.prototype.parseCommonHeaders = function(opt, headers, signatureContext) {
    for (var key in commonHeaders) {
      if ({}.hasOwnProperty.call(commonHeaders, key)) {
        opt.InterfaceResult[commonHeaders[key]] = headers[key]
      }
    }
    opt.InterfaceResult.RequestId = headers[signatureContext.headerPrefix + 'request-id']
    opt.InterfaceResult.Id2 = headers[signatureContext.headerPrefix + 'id-2']
    opt.CommonMsg.RequestId = opt.InterfaceResult.RequestId
    opt.CommonMsg.Id2 = opt.InterfaceResult.Id2
  }

  Utils.prototype.contrustCommonMsg = function(opt, obj, headers, signatureContext) {
    opt.InterfaceResult = {}
    this.parseCommonHeaders(opt, headers, signatureContext)
    for (var key in obj) {
      if (obj[key].location !== 'header') {
        continue
      }
      var sentAs = obj[key].sentAs || key

      if (obj[key].withPrefix) {
        sentAs = signatureContext.headerPrefix + sentAs
      }

      if (obj[key].type === 'object') {
        opt.InterfaceResult[key] = parseObjectFromHeaders(sentAs, headers)
      } else {
        var val = null
        if (sentAs in headers) {
          val = headers[sentAs]
        } else if (sentAs.toLowerCase() in headers) {
          val = headers[sentAs.toLowerCase()]
        }
        if (val !== null) {
          opt.InterfaceResult[key] = val
        }
      }
    }
  }

  Utils.prototype.getRequest = function(methodName, serverback, signatureContext, retryCount, params, bc) {
    var regionDomains = this.regionDomains
    var opt = {}
    var log = this.log
    var model = signatureContext.signature === 'obs' ? obsModel[methodName + 'Output'] : v2Model[methodName + 'Output']
    model = model || {}
    var obj = model.parameters || {}
    opt.CommonMsg = {
      Status: serverback.status,
      Code: '',
      Message: '',
      HostId: '',
      RequestId: '',
      InterfaceResult: null
    }

    var headers = serverback.headers
    var headersStr = headerTostring(headers)

    log.runLog('info', methodName, 'get response start, statusCode:' + serverback.status)
    log.runLog('debug', methodName, 'response msg :statusCode:' + serverback.status + ', headers:' + headersStr)

    var doLog = function doLog() {
      var logMsg = 'Status:' + opt.CommonMsg.Status + ', Code:' + opt.CommonMsg.Code + ', Message:' + opt.CommonMsg.Message
      log.runLog('debug', methodName, 'exec interface ' + methodName + ' finish, ' + logMsg)
      bc(null, opt)
    }

    if (serverback.status >= 300 && serverback.status < 400 && serverback.status !== 304 && retryCount <= 5) {
      var _location = headers.location || headers.Location
      if (_location) {
        var err = 'http code is 3xx, need to redirect to ' + _location
        log.runLog('warn', methodName, err)
        var redirectErr = new Error('redirect')
        redirectErr.location = _location
        redirectErr.bucketLocation = headers['x-amz-bucket-region'] || headers['x-obs-bucket-region']
        return bc(redirectErr)
      }
      var bucketLocation = headers['x-amz-bucket-region'] || headers['x-obs-bucket-location']
      if (bucketLocation && regionDomains[bucketLocation]) {
        var regionServer = (this.isSecure ? 'https://' : 'http://') + regionDomains[bucketLocation]
        if (isFunction(this.setRequestHeaderHook)) {
          this.setRequestHeaderHook(headers, params, methodName, regionDomains[bucketLocation])
        }
        var _err = 'get redirect code 3xx, need to redirect to' + regionServer
        log.runLog('error', methodName, _err)
        var _redirectErr = new Error('redirect')
        _redirectErr.location = regionServer
        return bc(_redirectErr)
      }
      log.runLog('error', methodName, 'get redirect code 3xx, but no location in headers')
    }

    if (serverback.status < 300) {
      var _body = serverback.data
      this.contrustCommonMsg(opt, obj, headers, signatureContext)
      var _respMsg = 'Status: ' + opt.CommonMsg.Status + ', headers: ' + headersStr
      if (_body) {
        _respMsg += 'body length: ' + _body.length
        log.runLog('debug', methodName, 'response body length:' + _body.length)
      }
      log.runLog('debug', methodName, _respMsg)

      if (_body && 'data' in model) {
        if (model.data.type === 'xml') {
          var that = this
          return makeObjFromXml(_body, function(err, result) {
            if (err) {
              log.runLog('error', methodName, 'change xml to json err [' + headerTostring(err) + ']')
              return bc(err, null)
            }

            var tempResult = result
            if (model.data.xmlRoot && model.data.xmlRoot in tempResult) {
              tempResult = result[model.data.xmlRoot]
            }
            var ifRootXMlDecode = !!tempResult.EncodingType
            if (isObject(tempResult)) {
              for (var key in obj) {
                if (obj[key].location === 'xml') {
                  opt.InterfaceResult[key] = that.jsonToObject(obj, tempResult, key, ifRootXMlDecode)[key]
                }
              }
            }

            doLog()
          })
        }

        if (model.data.type === 'body') {
          for (var key in obj) {
            if (obj[key].location === 'body') {
              opt.InterfaceResult[key] = _body
              break
            }
          }
        }
      }
      return doLog()
    }

    var body = serverback.data
    var respMsg = 'Status: ' + opt.CommonMsg.Status + ', headers: ' + headersStr
    if (body !== '') {
      respMsg += 'body: ' + body
      log.runLog('debug', methodName, 'response body :' + body)
    }
    opt.CommonMsg.RequestId = headers[signatureContext.headerPrefix + 'request-id']
    opt.CommonMsg.Id2 = headers[signatureContext.headerPrefix + 'id2']
    opt.CommonMsg.Indicator = headers['x-reserved-indicator']

    log.runLog('info', methodName, 'request finished with request id:' + opt.CommonMsg.RequestId)
    log.runLog('debug', methodName, respMsg)

    if (!body) {
      return doLog()
    }

    return makeObjFromXml(body, function(err, re) {
      if (err) {
        log.runLog('error', methodName, 'change xml to json err [' + headerTostring(err) + ']')
        opt.CommonMsg.Message = err.message
      } else if (re) {
        if ('Error' in re) {
          var errMsg = re.Error
          for (var param in errMsg) {
            if (errMsg[param] && errMsg[param]['#text']) {
              opt.CommonMsg[param] = errMsg[param]['#text']
            }
          }
        } else {
          var _errMsg = re
          if ('code' in _errMsg) {
            opt.CommonMsg.Code = _errMsg.code
          }
          if ('message' in _errMsg) {
            opt.CommonMsg.Message = _errMsg.message
          }
          if ('hostId' in _errMsg) {
            opt.CommonMsg.HostId = _errMsg.hostId
          }
          if ('request_id' in _errMsg && _errMsg.request_id) {
            opt.CommonMsg.RequestId = _errMsg.request_id
          }
        }

        log.runLog('error', methodName, 'request error with error code:' + opt.CommonMsg.Code + ', error message:' + opt.CommonMsg.Message + ', request id:' + opt.CommonMsg.RequestId)
      }
      doLog()
    })
  }

  Utils.prototype.makeRequest = function(methodName, opt, retryCount, bc) {
    var log = this.log
    // let server = this.server;
    var body = opt.xml || null
    var signatureContext = opt.signatureContext || this.signatureContext
    delete opt.headers.Authorization // retry bug fix

    if (opt.dstFile === 'file') {
      var queryParams = {}
      if (opt.urlPath) {
        var _path2 = opt.urlPath.slice(1)
        var arrPath = _path2.split('&')
        for (var i = 0; i < arrPath.length; i++) {
          if (arrPath[i].indexOf('=') === -1) {
            queryParams[arrPath[i]] = ''
          } else {
            var temp = arrPath[i].split('=')
            queryParams[temp[0]] = temp[1]
          }
        }
      }

      var rawUri = opt.rawUri.split('/')
      var bucketName = rawUri[1]
      var objectKey = opt.rawUri.slice(('/' + bucketName + '/').length)

      var ret = {}
      ret.CommonMsg = {
        Status: 0,
        Code: '',
        Message: '',
        HostId: ''
      }
      ret.InterfaceResult = {}
      var model = signatureContext.signature === 'obs' ? obsModel[methodName + 'Output'] : v2Model[methodName + 'Output']
      var obj = model.parameters
      for (var key in obj) {
        if (obj[key].location === 'body') {
          ret.InterfaceResult[key] = this.createSignedUrlSync({
            Method: opt.method,
            Bucket: bucketName,
            Key: objectKey,
            Expires: 3600,
            Headers: opt.headers,
            QueryParams: queryParams,
            signatureContext: signatureContext
          })
          break
        }
      }
      return bc(null, ret)
    }

    var requestDate = opt.$requestParam.RequestDate
    var nowDate = void 0
    var requestDateType = Object.prototype.toString.call(requestDate)
    if (requestDateType === '[object Date]') {
      nowDate = requestDate
    } else if (requestDateType === '[object String]') {
      try {
        nowDate = new Date()
        nowDate.setTime(Date.parse(requestDate))
      } catch (e) {
        // ignore
      }
    }

    if (!nowDate) {
      nowDate = new Date()
    }

    var utcDateStr = nowDate.toUTCString()
    var isV4 = signatureContext.signature.toLowerCase() === 'v4'
    opt.headers[signatureContext.headerPrefix + 'date'] = isV4 ? getDates(utcDateStr)[1] : utcDateStr
    var path = (opt.requestUri ? opt.requestUri : opt.uri) + opt.urlPath

    if (this.ak && this.sk && methodName !== negotiateMethod) {
      if (this.securityToken) {
        opt.headers[signatureContext.headerPrefix + 'security-token'] = this.securityToken
      }
      if (isV4) {
        this.v4Auth(opt, methodName, signatureContext)
      } else {
        this.doAuth(opt, methodName, signatureContext)
      }
    }

    var ex = opt.headers
    if (isFunction(this.setRequestHeaderHook)) {
      this.setRequestHeaderHook(ex, opt.$requestParam, methodName)
    }
    var host = ex.Host
    var method = opt.method
    var header_msg = {}
    for (var _key2 in ex) {
      if ({}.hasOwnProperty.call(ex, _key2)) {
        header_msg[_key2] = ex[_key2]
      }
    }
    header_msg.Authorization = '****'
    var msg = 'method:' + method + ', path:' + path + 'headers:' + headerTostring(header_msg)
    if (body) {
      msg += 'body:' + body
    }
    log.runLog('info', methodName, 'prepare request parameters ok,then Send request to service start')
    log.runLog('debug', methodName, 'request msg:' + msg)

    var _isSecure = opt.protocol ? opt.protocol.toLowerCase().indexOf('https') === 0 : this.isSecure
    var port = opt.port || this.port

    // avoid to set unsafe headers
    delete ex.Host
    delete ex['Content-Length']

    // 	ex['X-Requested-With'] = "XMLHttpRequest";
    var responseType = 'text'
    if (opt.dstFile && opt.dstFile !== 'file' && (opt.dstFile === 'arraybuffer' || opt.dstFile === 'blob')) {
      responseType = String(opt.dstFile)
    }

    var start = nowDate.getTime()
    var that = this

    var dealingError = function dealingError(err) {
      // with angular, headerTostring may lead to exception.
      try {
        var headerStr = headerTostring(err)
        log.runLog('error', methodName, 'Send request to service error [' + headerStr + ']')
      } catch (e) {
        if (err.toString) {
          log.runLog('error', methodName, 'Send request to service error [' + err.toString() + ']')
        }
      }
      log.runLog('info', methodName, 'http cost ' + (new Date().getTime() - start) + ' ms')
      bc(err, null)
    }

    if (!this.useRawXhr) {
      var onUploadProgress = null
      var onDownloadProgress = null
      if (isFunction(opt.ProgressCallback)) {
        var progressListener = function progressListener(event) {
          if (event.lengthComputable) {
            opt.ProgressCallback(event.loaded, event.total, (new Date().getTime() - start) / 1000)
          }
        }
        if (method === 'GET') {
          onDownloadProgress = progressListener
        } else if (method === 'PUT' || method === 'POST') {
          onUploadProgress = progressListener
        }
      }
      var portInfo = ':' + port
      if (host.indexOf(':') >= 0) {
        portInfo = ''
      }
      // 适配cf2,在请求中增加通配符
      var baseUrl = ''
      var httpPrefix = _isSecure ? 'https://' : 'http://'
      if (this.urlPrefix && isFunction(this.setRequestHeaderHook) && methodName !== 'InitiateMultipartUpload' && methodName !== 'UploadPart' && methodName !== 'CompleteMultipartUpload') {
        var defaultRegion = true
        if (opt.$requestParam['hasRegion'] || opt.$requestParam['redirectRegion']) {
          defaultRegion = false
        }

        var portFlag = ''
        if (port === 5443) {
          portFlag = '-5443'
        }

        if (defaultRegion) {
          if (opt.$requestParam['Bucket']) {
            if (opt.$requestParam['Bucket'].indexOf('.') !== -1) {
              baseUrl = httpPrefix + this.urlPrefix + '/bucket' + portFlag
            }
            baseUrl = httpPrefix + this.urlPrefix + '/bucket' + portFlag
          } else {
            if (path.split('?')[0] === '/') {
              baseUrl = httpPrefix + this.urlPrefix + portFlag
            } else {
              baseUrl = httpPrefix + this.urlPrefix + '/place' + portFlag
            }
          }
        } else {
          if (opt.$requestParam['Bucket']) {
            baseUrl = httpPrefix + this.urlPrefix + '/region-bucket' + portFlag
          } else {
            baseUrl = httpPrefix + this.urlPrefix + '/region' + portFlag
          }
        }
      } else {
        baseUrl = httpPrefix + host + portInfo
      }

      var reopt = {
        method: method,
        // fix bug, axios will abandon the base url if the request url starts with '//', so use the completed url to avoid it
        url: baseUrl + path,
        withCredentials: false,
        headers: ex,
        validateStatus: function validateStatus(status) {
          return status >= 200
        },
        maxRedirects: 0,
        responseType: responseType,
        data: body,
        timeout: this.timeout * 1000,
        onUploadProgress: onUploadProgress,
        onDownloadProgress: onDownloadProgress,
        cancelToken: new axios.CancelToken(function(cancelHook) {
          opt.$requestParam.cancelHook = cancelHook
        })
      }
      if (opt.srcFile) {
        if (!(opt.srcFile instanceof window.File) && !(opt.srcFile instanceof window.Blob)) {
          return bc(new Error('source file must be an instance of window.File or window.Blob'), null)
        }

        var srcFile = opt.srcFile
        try {
          if (opt.Offset >= 0 && opt.PartSize > 0) {
            srcFile = this.sliceBlob(srcFile, opt.Offset, opt.Offset + opt.PartSize)
          } else if ('ContentLength' in opt) {
            var contentLength = parseInt(opt.ContentLength, 10)
            if (contentLength > 0) {
              srcFile = this.sliceBlob(srcFile, 0, contentLength)
            }
          }
        } catch (e) {
          return bc(e)
        }

        reopt.data = srcFile
      }
      axios.request(reopt).then(function(response) {
        log.runLog('info', methodName, 'http cost ' + (new Date().getTime() - start) + ' ms')
        that.getRequest(methodName, response, signatureContext, retryCount, opt.$requestParam, bc)
      }).catch(function(err) {
        dealingError(err)
      })
      return
    }

    var xhr = null
    // Firefox, Opera 8.0+, Safari
    try {
      xhr = new XMLHttpRequest()
    } catch (e) {
      try {
        // InternetExplorer
        xhr = new ActiveXObject('Msxml2.XMLHTTP')
      } catch (e1) {
        try {
          xhr = new ActiveXObject('Microsoft.XMLHTTP')
        } catch (e2) {}
      }
    }

    if (xhr === null) {
      return bc(new Error('XHR is not available'), null)
    }

    if (opt.srcFile) {
      if (!(opt.srcFile instanceof window.File) && !(opt.srcFile instanceof window.Blob)) {
        return bc(new Error('source file must be an instance of window.File or window.Blob'), null)
      }

      try {
        var _srcFile = opt.srcFile
        if (opt.Offset >= 0 && opt.PartSize > 0) {
          _srcFile = this.sliceBlob(_srcFile, opt.Offset, opt.Offset + opt.PartSize)
        } else if ('ContentLength' in opt) {
          var _contentLength = parseInt(opt.ContentLength, 10)
          if (_contentLength > 0) {
            _srcFile = this.sliceBlob(_srcFile, 0, _contentLength)
          }
        }
        body = _srcFile
      } catch (e) {
        return bc(e)
      }
    }
    xhr.open(method, (_isSecure ? 'https://' + this.urlPrefix + host : 'http://' + this.urlPrefix + host) + path)
    xhr.withCredentials = false
    for (var _key3 in ex) {
      if ({}.hasOwnProperty.call(ex, _key3)) {
        xhr.setRequestHeader(_key3, ex[_key3])
      }
    }
    xhr.timeout = that.timeout * 1000
    xhr.responseType = responseType
    opt.$requestParam.cancelHook = function() {
      xhr.abort()
    }
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4 && xhr.status >= 200) {
        log.runLog('info', methodName, 'http cost ' + (new Date().getTime() - start) + ' ms')
        var headers = xhr.getAllResponseHeaders()
        var arr = headers.trim().split(/[\r\n]+/)
        var headerMap = {}
        for (var _i = 0; _i < arr.length; _i++) {
          var line = arr[_i]
          var parts = line.split(': ')
          var header = parts.shift()
          var value = parts.join(': ')
          headerMap[header.toLowerCase()] = value
        }
        var data = xhr.response
        if (!data && (responseType === '' || responseType === 'text')) {
          data = xhr.responseText
        }
        var response = {
          status: xhr.status,
          headers: headerMap,
          data: data
        }
        that.getRequest(methodName, response, signatureContext, retryCount, opt.$requestParam, bc)
      }
    }

    var handled = false
    var errHandler = function errHandler(err) {
      if (handled) {
        return
      }
      handled = true
      dealingError(err)
    }

    // For the compatibility with Axios
    xhr.ontimeout = function() {
      errHandler(new Error('timeout of ' + xhr.timeout + 'ms exceed'))
    }

    // For the compatibility with Axios
    xhr.onerror = function() {
      errHandler(new Error('Network Error'))
    }

    // For the compatibility with Axios
    xhr.onabort = function() {
      errHandler(new Error('Cancel'))
    }

    if (xhr.upload) {
      // For the compatibility with Axios
      xhr.upload.ontimeout = function() {
        errHandler(new Error('timeout of ' + xhr.timeout + 'ms exceed'))
      }

      // For the compatibility with Axios
      xhr.upload.onerror = function() {
        errHandler(new Error('Network Error'))
      }

      // For the compatibility with Axios
      xhr.upload.onabort = function(e) {
        errHandler(new Error('Cancel'))
      }
    }

    if (isFunction(opt.ProgressCallback)) {
      if (method === 'GET' || !xhr.upload) {
        xhr.onprogress = function(event) {
          if (event.lengthComputable) {
            opt.ProgressCallback(event.loaded, event.total, (new Date().getTime() - start) / 1000)
          }
        }
      } else if (method === 'PUT' || method === 'POST') {
        xhr.upload.onprogress = function(event) {
          if (event.lengthComputable) {
            opt.ProgressCallback(event.loaded, event.total, (new Date().getTime() - start) / 1000)
          }
        }
      }
    }
    xhr.send(body)
  }

  Utils.prototype.sendRequest = function(funcName, opt, backcall, retryCount) {
    if (retryCount === undefined) {
      retryCount = 1
    }
    var that = this
    that.makeRequest(funcName, opt, retryCount, function(err, msg) {
      if (err && err.message === 'redirect') {
        var uri = urlLib.parse(err.location)
        if (err.bucketLocation && uri.hostname.indexOf(opt.$requestParam['Bucket']) !== -1) {
          opt.$requestParam.redirectRegion = err.bucketLocation
        }
        opt.headers.Host = uri.hostname
        opt.protocol = uri.protocol
        opt.port = uri.port || (opt.protocol && opt.protocol.toLowerCase().indexOf('https') === 0 ? 443 : 80)
        that.sendRequest(funcName, opt, backcall, retryCount + 1)
      } else {
        backcall(err, msg)
      }
    })
  }

  Utils.prototype.doAuth = function(opt, methodName, signatureContext) {
    var interestHeader = ['Content-MD5', 'Content-Type']
    var stringToSign = opt.method + '\n'
    for (var i = 0; i < interestHeader.length; i++) {
      if (interestHeader[i] in opt.headers) {
        stringToSign += opt.headers[interestHeader[i]]
      }
      stringToSign += '\n'
    }
    if (!(signatureContext.headerPrefix + 'date' in opt.headers)) {
      stringToSign += opt.headers.Date
    }
    stringToSign += '\n'

    var temp = []
    for (var originKey in opt.headers) {
      if ({}.hasOwnProperty.call(opt.headers, originKey)) {
        var lowerKey = originKey.toLowerCase()
        if (lowerKey.indexOf(signatureContext.headerPrefix) === 0) {
          temp.push({
            key: lowerKey,
            value: opt.headers[originKey]
          })
        }
      }
    }
    temp = temp.sort(function(obj1, obj2) {
      if (obj1.key < obj2.key) {
        return -1
      }
      if (obj1.key > obj2.key) {
        return 1
      }
      return 0
    })
    for (var _i2 = 0; _i2 < temp.length; _i2++) {
      var key = temp[_i2].key
      var val = key.indexOf(signatureContext.headerMetaPrefix) === 0 ? temp[_i2].value.trim() : temp[_i2].value
      stringToSign += key + ':' + val + '\n'
    }

    var path = opt.uri
    if (this.isCname) {
      if (path === '/') {
        path += opt.headers.Host + '/'
      } else if (path.indexOf('/') === 0) {
        path = '/' + opt.headers.Host + path
      }
    }
    if (opt.urlPath) {
      var _path = opt.urlPath.slice(1)
      var arrPath = _path.split('&').sort()
      var urlPath = ''
      for (var _i3 = 0; _i3 < arrPath.length; _i3++) {
        var listvar = arrPath[_i3].split('=')
        var _key4 = decodeURIComponent(listvar[0])
        if (allowedResourceParameterNames.indexOf(_key4.toLowerCase()) >= 0) {
          urlPath += urlPath === '' ? '?' : '&'
          urlPath += _key4
          if (listvar.length === 2 && listvar[1]) {
            urlPath += '=' + decodeURIComponent(listvar[1])
          }
        }
      }
      path += urlPath
    }
    stringToSign += path
    this.log.runLog('debug', methodName, 'stringToSign:' + stringToSign)
    opt.headers.Authorization = signatureContext.authPrefix + ' ' + this.ak + ':' + crypto.createHmac('sha1', this.sk).update(stringToSign).digest('base64')
  }

  Utils.prototype.v4Auth = function(opt, methodName, signatureContext) {
    opt.headers[signatureContext.headerPrefix + 'content-sha256'] = CONTENT_SHA256
    var header = opt.headers
    var log = this.log
    var shortDate = null
    var longDate = null

    if (signatureContext.headerPrefix + 'date' in header) {
      longDate = header[signatureContext.headerPrefix + 'date']
      shortDate = longDate.slice(0, longDate.indexOf('T'))
    } else {
      var dates = getDates(header.Date)
      shortDate = dates[0]
      longDate = dates[1]
    }

    var credenttial = this.ak + '/' + shortDate + '/' + this.region + '/s3/aws4_request'

    var signedAndCanonicalHeaders = getSignedAndCanonicalHeaders(header)

    var signedHeaders = signedAndCanonicalHeaders[0]
    var canonicalHeaders = signedAndCanonicalHeaders[1]

    var canonicalQueryString = ''
    if (opt.urlPath) {
      var path = opt.urlPath.slice(1)
      var arrPath = path.split('&')
      arrPath = arrPath.sort()
      for (var i = 0; i < arrPath.length; i++) {
        canonicalQueryString += arrPath[i]
        if (arrPath[i].indexOf('=') === -1) {
          canonicalQueryString += '='
        }
        if (i !== arrPath.length - 1) {
          canonicalQueryString += '&'
        }
      }
    }
    var canonicalRequest = opt.method + '\n'
    canonicalRequest += opt.uri + '\n'
    canonicalRequest += canonicalQueryString + '\n'
    canonicalRequest += canonicalHeaders + '\n'
    canonicalRequest += signedHeaders + '\n'
    canonicalRequest += CONTENT_SHA256
    log.runLog('debug', methodName, 'canonicalRequest:' + canonicalRequest)

    var signature = getV4Signature(shortDate, longDate, this.sk, this.region, canonicalRequest)

    opt.headers.Authorization = 'AWS4-HMAC-SHA256 Credential=' + credenttial + ',SignedHeaders=' + signedHeaders + ',Signature=' + signature
  }

  Utils.prototype.bufMD5 = function(buf) {
    return crypto.createHash('md5').update(buf).digest('base64')
  }

  Utils.prototype.rawBufMD5 = function(buf) {
    return crypto.createHash('md5').update(buf).digest('rawbase64')
  }

  Utils.prototype.createSignedUrlSync = function(param) {
    var signatureContext = param.signatureContext || this.signatureContext
    return signatureContext.signature.toLowerCase() === 'v4' ? this.createV4SignedUrlSync(param) : this.createV2SignedUrlSync(param)
  }

  Utils.prototype.createV2SignedUrlSync = function(param) {
    param = param || {}
    var signatureContext = param.signatureContext || this.signatureContext
    var method = param.Method ? String(param.Method) : 'GET'
    var bucketName = param.Bucket ? String(param.Bucket) : null
    var objectKey = param.Key ? String(param.Key) : null
    var specialParam = param.SpecialParam ? String(param.SpecialParam) : null
    if (signatureContext.signature.toLowerCase() === 'obs' && specialParam === 'storagePolicy') {
      specialParam = 'storageClass'
    } else if (signatureContext.signature.toLowerCase() === 'v2' && specialParam === 'storageClass') {
      specialParam = 'storagePolicy'
    }
    var policy = param.Policy ? String(param.Policy) : null
    var prefix = param.Prefix ? String(param.Prefix) : null
    var expires = param.Expires ? parseInt(param.Expires, 10) : 300
    var headers = {}
    if (param.Headers && param.Headers instanceof Object && !(param.Headers instanceof Array)) {
      for (var key in param.Headers) {
        if ({}.hasOwnProperty.call(param.Headers, key)) {
          headers[key] = param.Headers[key]
        }
      }
    }

    var queryParams = {}
    if (param.QueryParams && param.QueryParams instanceof Object && !(param.QueryParams instanceof Array)) {
      for (var _key5 in param.QueryParams) {
        if ({}.hasOwnProperty.call(param.QueryParams, _key5)) {
          queryParams[_key5] = param.QueryParams[_key5]
        }
      }
    }

    if (this.securityToken && !queryParams[signatureContext.headerPrefix + 'security-token']) {
      queryParams[signatureContext.headerPrefix + 'security-token'] = this.securityToken
    }

    var result = ''
    var resource = ''
    var host = this.server
    if (this.isCname) {
      resource += '/' + host + '/'
    } else if (bucketName) {
      resource += '/' + bucketName
      if (this.pathStyle) {
        result += '/' + bucketName
      } else {
        host = bucketName + '.' + host
        resource += '/'
      }
    }

    if (objectKey) {
      objectKey = encodeURIWithSafe(objectKey, '/')
      result += '/' + objectKey
      if (resource.lastIndexOf('/') !== resource.length - 1) {
        resource += '/'
      }
      resource += objectKey
    }

    if (resource === '') {
      resource = '/'
    }

    result += '?'

    if (specialParam) {
      queryParams[specialParam] = ''
    }

    if (signatureContext.signature.toLowerCase() === 'v2') {
      queryParams.AWSAccessKeyId = this.ak
    } else {
      queryParams.AccessKeyId = this.ak
    }

    if (expires < 0) {
      expires = 300
    }
    expires = parseInt(new Date().getTime() / 1000, 10) + expires

    if (policy && prefix) {
      queryParams.Policy = policy
      queryParams.prefix = prefix
    } else {
      queryParams.Expires = String(expires)
    }

    var interestHeaders = {}
    for (var name in headers) {
      if ({}.hasOwnProperty.call(headers, name)) {
        var _key6 = String(name).toLowerCase()
        if (_key6 === 'content-type' || _key6 === 'content-md5' || _key6.length > signatureContext.headerPrefix.length && _key6.slice(0, signatureContext.headerPrefix.length) === signatureContext.headerPrefix) {
          interestHeaders[_key6] = headers[name]
        }
      }
    }

    var queryParamsKeys = []
    for (var _key7 in queryParams) {
      if ({}.hasOwnProperty.call(queryParams, _key7)) {
        queryParamsKeys.push(_key7)
      }
    }
    queryParamsKeys.sort()
    var flag = false
    var _resource = []
    var safeKey = policy && prefix ? '' : '/'
    for (var i = 0; i < queryParamsKeys.length; i++) {
      var _key8 = queryParamsKeys[i]
      var val = queryParams[_key8]
      _key8 = encodeURIWithSafe(_key8, safeKey)
      val = encodeURIWithSafe(val, safeKey)
      result += _key8
      if (val) {
        result += '=' + val
      }
      if (allowedResourceParameterNames.indexOf(_key8.toLowerCase()) >= 0 || _key8.toLowerCase().indexOf(signatureContext.headerPrefix) === 0) {
        flag = true
        var _val = val ? _key8 + '=' + decodeURIComponent(val) : _key8
        _resource.push(_val)
      }
      result += '&'
    }
    _resource = _resource.join('&')
    if (flag) {
      _resource = '?' + _resource
    }
    resource += _resource
    var stringToSign = [method]
    stringToSign.push('\n')

    if ('content-md5' in interestHeaders) {
      stringToSign.push(interestHeaders['content-md5'])
    }
    stringToSign.push('\n')

    if ('content-type' in interestHeaders) {
      stringToSign.push(interestHeaders['content-type'])
    }
    stringToSign.push('\n')
    if (policy && prefix) {
      stringToSign.push(policy)
    } else {
      stringToSign.push(String(expires))
    }

    stringToSign.push('\n')

    if (!(policy && prefix)) {
      var temp = []
      var _i4 = 0
      for (var _key9 in interestHeaders) {
        if (_key9.length > signatureContext.headerPrefix.length && _key9.slice(0, signatureContext.headerPrefix.length) === signatureContext.headerPrefix) {
          temp[_i4++] = _key9
        }
      }
      temp = temp.sort()
      for (var j = 0; j < temp.length; j++) {
        stringToSign.push(temp[j])
        stringToSign.push(':')
        stringToSign.push(interestHeaders[temp[j]])
        stringToSign.push('\n')
      }

      stringToSign.push(resource)
    }
    var hmac = crypto.createHmac('sha1', this.sk)
    hmac.update(stringToSign.join(''))
    if (policy && prefix) {
      result += 'Signature=' + encodeURIWithSafe(hmac.digest('base64'))
    } else {
      result += 'Signature=' + encodeURIWithSafe(hmac.digest('base64'), '/')
    }

    return {
      ActualSignedRequestHeaders: headers,
      SignedUrl: (this.isSecure ? 'https' : 'http') + '://' + host + ':' + this.port + result
    }
  }

  Utils.prototype.createV4SignedUrlSync = function(param) {
    param = param || {}
    var signatureContext = param.signatureContext || this.signatureContext
    var method = param.Method ? String(param.Method) : 'GET'
    var bucketName = param.Bucket ? String(param.Bucket) : null
    var objectKey = param.Key ? String(param.Key) : null
    var specialParam = param.SpecialParam ? String(param.SpecialParam) : null

    if (specialParam === 'storageClass') {
      specialParam = 'storagePolicy'
    }

    var expires = param.Expires ? parseInt(param.Expires, 10) : 300
    var headers = {}
    if (param.Headers && param.Headers instanceof Object && !(param.Headers instanceof Array)) {
      for (var key in param.Headers) {
        if ({}.hasOwnProperty.call(param.Headers, key)) {
          headers[key] = param.Headers[key]
        }
      }
    }

    var queryParams = {}
    if (param.QueryParams && param.QueryParams instanceof Object && !(param.QueryParams instanceof Array)) {
      for (var _key10 in param.QueryParams) {
        if ({}.hasOwnProperty.call(param.QueryParams, _key10)) {
          queryParams[_key10] = param.QueryParams[_key10]
        }
      }
    }

    if (this.securityToken && !queryParams[signatureContext.headerPrefix + 'security-token']) {
      queryParams[signatureContext.headerPrefix + 'security-token'] = this.securityToken
    }

    var result = ''
    var resource = ''
    var host = this.server
    if (bucketName) {
      if (this.pathStyle) {
        result += '/' + bucketName
        resource += '/' + bucketName
      } else {
        host = bucketName + '.' + host
      }
    }

    if (objectKey) {
      objectKey = encodeURIWithSafe(objectKey, '/')
      result += '/' + objectKey
      resource += '/' + objectKey
    }

    if (resource === '') {
      resource = '/'
    }

    result += '?'

    if (specialParam) {
      queryParams[specialParam] = ''
    }

    if (expires < 0) {
      expires = 300
    }

    var utcDateStr = headers['date'] || headers['Date'] || new Date().toUTCString()

    var dates = getDates(utcDateStr)
    var shortDate = dates[0]
    var longDate = dates[1]

    headers.Host = host + (this.port === 80 || this.port === 443 ? '' : ':' + this.port)

    queryParams['X-Amz-Algorithm'] = 'AWS4-HMAC-SHA256'
    queryParams['X-Amz-Credential'] = this.ak + '/' + shortDate + '/' + this.region + '/s3/aws4_request'
    queryParams['X-Amz-Date'] = longDate
    queryParams['X-Amz-Expires'] = String(expires)

    var signedAndCanonicalHeaders = getSignedAndCanonicalHeaders(headers)

    queryParams['X-Amz-SignedHeaders'] = signedAndCanonicalHeaders[0]

    var _queryParams = {}
    var queryParamsKeys = []
    for (var _key11 in queryParams) {
      if ({}.hasOwnProperty.call(queryParams, _key11)) {
        var val = queryParams[_key11]
        _key11 = encodeURIWithSafe(_key11, '/')
        val = encodeURIWithSafe(val)
        _queryParams[_key11] = val
        queryParamsKeys.push(_key11)
        result += _key11
        if (val) {
          result += '=' + val
        }
        result += '&'
      }
    }

    var canonicalQueryString = ''

    queryParamsKeys.sort()

    for (var i = 0; i < queryParamsKeys.length;) {
      canonicalQueryString += queryParamsKeys[i] + '=' + _queryParams[queryParamsKeys[i]]
      if (++i !== queryParamsKeys.length) {
        canonicalQueryString += '&'
      }
    }

    var canonicalRequest = method + '\n'
    canonicalRequest += resource + '\n'
    canonicalRequest += canonicalQueryString + '\n'
    canonicalRequest += signedAndCanonicalHeaders[1] + '\n'
    canonicalRequest += signedAndCanonicalHeaders[0] + '\n'
    canonicalRequest += 'UNSIGNED-PAYLOAD'

    var signature = getV4Signature(shortDate, longDate, this.sk, this.region, canonicalRequest)
    result += 'X-Amz-Signature=' + encodeURIWithSafe(signature)
    return {
      ActualSignedRequestHeaders: headers,
      SignedUrl: (this.isSecure ? 'https' : 'http') + '://' + host + ':' + this.port + result
    }
  }

  Utils.prototype.createPostSignatureSync = function(param) {
    var signatureContext = param.signatureContext || this.signatureContext
    if (signatureContext.signature === 'v4') {
      return this.createV4PostSignatureSync(param)
    }

    param = param || {}
    var bucketName = param.Bucket ? String(param.Bucket) : null
    var objectKey = param.Key ? String(param.Key) : null
    var expires = param.Expires ? parseInt(param.Expires, 10) : 300
    var formParams = {}

    if (param.FormParams && param.FormParams instanceof Object && !(param.FormParams instanceof Array)) {
      for (var key in param.FormParams) {
        if ({}.hasOwnProperty.call(param.FormParams, key)) {
          formParams[key] = param.FormParams[key]
        }
      }
    }

    if (this.securityToken && !formParams[signatureContext.headerPrefix + 'security-token']) {
      formParams[signatureContext.headerPrefix + 'security-token'] = this.securityToken
    }

    var expireDate = new Date()
    expireDate.setTime(parseInt(new Date().getTime(), 10) + expires * 1000)
    expireDate = getExpireDate(expireDate.toUTCString())

    if (bucketName) {
      formParams.bucket = bucketName
    }

    if (objectKey) {
      formParams.key = objectKey
    }

    var policy = []
    policy.push('{"expiration":"')
    policy.push(expireDate)
    policy.push('", "conditions":[')

    var matchAnyBucket = true
    var matchAnyKey = true

    var conditionAllowKeys = ['acl', 'bucket', 'key', 'success_action_redirect', 'redirect', 'success_action_status']

    for (var _key12 in formParams) {
      if (!_key12) {
        continue
      }
      var val = formParams[_key12]
      _key12 = String(_key12).toLowerCase()

      if (_key12 === 'bucket') {
        matchAnyBucket = false
      } else if (_key12 === 'key') {
        matchAnyKey = false
      }
      if (allowedResponseHttpHeaderMetadataNames.indexOf(_key12) < 0 && conditionAllowKeys.indexOf(_key12) < 0 && _key12.indexOf(signatureContext.headerPrefix) !== 0) {
        continue
      }

      policy.push('{"')
      policy.push(_key12)
      policy.push('":"')
      policy.push(val !== null ? String(val) : '')
      policy.push('"},')
    }

    if (matchAnyBucket) {
      policy.push('["starts-with", "$bucket", ""],')
    }

    if (matchAnyKey) {
      policy.push('["starts-with", "$key", ""],')
    }

    policy.push(']}')

    var originPolicy = policy.join('')

    if (window.btoa) {
      policy = window.btoa(originPolicy)
    } else {
      policy = Base64.encode(originPolicy)
    }
    var signature = crypto.createHmac('sha1', this.sk).update(policy).digest('base64')

    return {
      OriginPolicy: originPolicy,
      Policy: policy,
      Signature: signature,
      Token: this.ak + ':' + signature + ':' + policy
    }
  }

  Utils.prototype.createV4PostSignatureSync = function(param) {
    param = param || {}
    var signatureContext = param.signatureContext || this.signatureContext
    var bucketName = param.Bucket ? String(param.Bucket) : null
    var objectKey = param.Key ? String(param.Key) : null
    var expires = param.Expires ? parseInt(param.Expires, 10) : 300
    var formParams = {}

    if (param.FormParams && param.FormParams instanceof Object && !(param.FormParams instanceof Array)) {
      for (var key in param.FormParams) {
        if ({}.hasOwnProperty.call(param.FormParams, key)) {
          formParams[key] = param.FormParams[key]
        }
      }
    }

    if (this.securityToken && !formParams[signatureContext.headerPrefix + 'security-token']) {
      formParams[signatureContext.headerPrefix + 'security-token'] = this.securityToken
    }

    var utcDateStr = new Date().toUTCString()
    var dates = getDates(utcDateStr)
    var shortDate = dates[0]
    var longDate = dates[1]

    var credential = this.ak + '/' + shortDate + '/' + this.region + '/s3/aws4_request'

    var expireDate = new Date()
    expireDate.setTime(parseInt(new Date().getTime(), 10) + expires * 1000)

    expireDate = getExpireDate(expireDate.toUTCString())

    formParams['X-Amz-Algorithm'] = 'AWS4-HMAC-SHA256'
    formParams['X-Amz-Date'] = longDate
    formParams['X-Amz-Credential'] = credential

    if (bucketName) {
      formParams.bucket = bucketName
    }

    if (objectKey) {
      formParams.key = objectKey
    }

    var policy = []
    policy.push('{"expiration":"')
    policy.push(expireDate)
    policy.push('", "conditions":[')

    var matchAnyBucket = true
    var matchAnyKey = true

    var conditionAllowKeys = ['acl', 'bucket', 'key', 'success_action_redirect', 'redirect', 'success_action_status']

    for (var _key13 in formParams) {
      if (!_key13) {
        continue
      }
      var val = formParams[_key13]
      _key13 = String(_key13).toLowerCase()

      if (_key13 === 'bucket') {
        matchAnyBucket = false
      } else if (_key13 === 'key') {
        matchAnyKey = false
      }

      if (allowedResponseHttpHeaderMetadataNames.indexOf(_key13) < 0 && conditionAllowKeys.indexOf(_key13) < 0 && _key13.indexOf(signatureContext.headerPrefix) !== 0) {
        continue
      }

      policy.push('{"')
      policy.push(_key13)
      policy.push('":"')
      policy.push(val !== null ? String(val) : '')
      policy.push('"},')
    }

    if (matchAnyBucket) {
      policy.push('["starts-with", "$bucket", ""],')
    }

    if (matchAnyKey) {
      policy.push('["starts-with", "$key", ""],')
    }

    policy.push(']}')

    var originPolicy = policy.join('')

    if (window.btoa) {
      policy = window.btoa(originPolicy)
    } else {
      policy = Base64.encode(originPolicy)
    }

    var signature = createV4Signature(shortDate, this.sk, this.region, policy)

    return {
      OriginPolicy: originPolicy,
      Policy: policy,
      Algorithm: formParams['X-Amz-Algorithm'],
      Credential: formParams['X-Amz-Credential'],
      Date: formParams['X-Amz-Date'],
      Signature: signature
    }
  }

  return Utils
});

/**
 * Copyright 2019 Huawei Technologies Co.,Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
 * this file except in compliance with the License.  You may obtain a copy of the
 * License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 */

(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    define('enums', [], factory)
  } else {
    root['enums'] = factory()
  }
})(undefined || window, function() {
  var exports = {}
  exports.AclPrivate = 'private'
  exports.AclPublicRead = 'public-read'
  exports.AclPublicReadWrite = 'public-read-write'
  exports.AclPublicReadDelivered = 'public-read-delivered'
  exports.AclPublicReadWriteDelivered = 'public-read-write-delivered'
  exports.AclAuthenticatedRead = 'authenticated-read'
  exports.AclBucketOwnerRead = 'bucket-owner-read'
  exports.AclBucketOwnerFullControl = 'bucket-owner-full-control'
  exports.AclLogDeliveryWrite = 'log-delivery-write'

  exports.StorageClassStandard = 'STANDARD'
  exports.StorageClassWarm = 'WARM'
  exports.StorageClassCold = 'COLD'

  exports.PermissionRead = 'READ'
  exports.PermissionWrite = 'WRITE'
  exports.PermissionReadAcp = 'READ_ACP'
  exports.PermissionWriteAcp = 'WRITE_ACP'
  exports.PermissionFullControl = 'FULL_CONTROL'

  exports.GroupAllUsers = 'AllUsers'
  exports.GroupAuthenticatedUsers = 'AuthenticatedUsers'
  exports.GroupLogDelivery = 'LogDelivery'

  exports.RestoreTierExpedited = 'Expedited'
  exports.RestoreTierStandard = 'Standard'
  exports.RestoreTierBulk = 'Bulk'

  exports.GranteeGroup = 'Group'
  exports.GranteeUser = 'CanonicalUser'

  exports.CopyMetadata = 'COPY'
  exports.ReplaceMetadata = 'REPLACE'

  exports.EventObjectCreatedAll = 'ObjectCreated:*'
  exports.EventObjectCreatedPut = 'ObjectCreated:Put'
  exports.EventObjectCreatedPost = 'ObjectCreated:Post'
  exports.EventObjectCreatedCopy = 'ObjectCreated:Copy'
  exports.EventObjectCreatedCompleteMultipartUpload = 'ObjectCreated:CompleteMultipartUpload'
  exports.EventObjectRemovedAll = 'ObjectRemoved:*'
  exports.EventObjectRemovedDelete = 'ObjectRemoved:Delete'
  exports.EventObjectRemovedDeleteMarkerCreated = 'ObjectRemoved:DeleteMarkerCreated'

  return exports
});

/**
 * Copyright 2019 Huawei Technologies Co.,Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
 * this file except in compliance with the License.  You may obtain a copy of the
 * License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 */
(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    define('posix', [], factory)
  } else {
    root['posix'] = factory()
  }
})(undefined || window, function() {
  var wrapCallback = function wrapCallback(callback, log, methodName) {
    callback = callback || function() {}
    var start = new Date().getTime()
    return function(err, result) {
      log.runLog('info', methodName, 'ObsClient cost ' + (new Date().getTime() - start) + ' ms')
      if (Object.prototype.toString.call(err) === '[object String]') {
        return callback(new Error(err), result)
      }

      return callback(err, result)
    }
  }

  var wrapEventCallback = function wrapEventCallback(eventCallback) {
    eventCallback = eventCallback || function() {}
    return function(t, key, result) {
      if (Object.prototype.toString.call(result) === '[object Error]') {
        return eventCallback(t, key, result)
      }

      if (Object.prototype.toString.call(result) === '[object String]') {
        return eventCallback(t, key, new Error(result))
      }

      if (!result) {
        return
      }

      if (result.CommonMsg.Status > 300) {
        return eventCallback(t, key, new Error('status:' + result.CommonMsg.Status + ', code:' + result.CommonMsg.Code + ', message:' + result.CommonMsg.Message))
      }

      eventCallback(t, key, result)
    }
  }

  var checkPrefix = function checkPrefix(prefix) {
    if (Object.prototype.toString.call(prefix) === '[object String]' && prefix.lastIndexOf('/') !== prefix.length - 1) {
      prefix += '/'
    }
    return prefix
  }

  var posix = {}
  posix.extend = function(ObsClient) {
    ObsClient.prototype.dropFile = function(param, callback) {
      this.deleteObject(param, callback)
    }

    ObsClient.prototype.dropFolder = function(param, callback) {
      var that = this
      param = param || {}
      var _callback = wrapCallback(callback, that.log, 'dropFolder')
      var eventCallback = wrapEventCallback(param.EventCallback)
      var taskNum = param.TaskNum || 1
      var runningTask = 0
      var taskQueue = []

      var doNext = function doNext() {
        while (runningTask < taskNum && taskQueue.length > 0) {
          taskQueue.shift()()
        }
      }

      var doDropOne = function doDropOne(key, ctx, done, dryRun) {
        if (dryRun) {
          ctx.finished++
          done(ctx)
          return
        }

        var task = function task() {
          runningTask++
          that.dropFile({
            Bucket: ctx.bucket,
            Key: key
          }, function(err, result) {
            runningTask--
            ctx.finished++
            doNext()
            if (err) {
              eventCallback('dropFileFailed', key, err)
              ctx.subDeleted = false
            } else if (result.CommonMsg.Status >= 300) {
              eventCallback('dropFileFailed', key, result)
              ctx.subDeleted = false
            } else {
              eventCallback('dropFileSucceed', key, result)
            }
            done(ctx)
          })
        }

        if (runningTask < taskNum) {
          task()
        } else {
          taskQueue.push(task)
        }
      }

      var delimiter = '/'

      var createDone = function createDone(subFolder, ctx, done) {
        return function(subCtx) {
          if (!subCtx.isTruncated && subCtx.finished === subCtx.total && subCtx.subDeleted) {
            doDropOne(subFolder, ctx, done, false)
          }
        }
      }

      var recursiveDropByFolder = function recursiveDropByFolder(ctx, bucket, prefix, marker, done) {
        runningTask++
        that.listObjects({
          Bucket: bucket,
          Prefix: prefix,
          Delimiter: delimiter,
          Marker: marker
        }, function(err, result) {
          runningTask--
          if (err) {
            return _callback(err)
          }

          if (result.CommonMsg.Status >= 300) {
            return _callback(null, result)
          }

          ctx.total += result.InterfaceResult.Contents.length
          ctx.total += result.InterfaceResult.CommonPrefixes.length
          if (ctx.total === 0) {
            done(ctx)
            return
          }

          ctx.isTruncated = result.InterfaceResult.IsTruncated === 'true'

          var createRecursiveDropByFolderTask = function createRecursiveDropByFolderTask(subFolder) {
            return function() {
              recursiveDropByFolder({ total: 0, finished: 0, isTruncated: false, bucket: bucket, subDeleted: true }, bucket, subFolder, null, createDone(subFolder, ctx, done))
            }
          }

          for (var j = 0; j < result.InterfaceResult.CommonPrefixes.length; j++) {
            var subFolder = checkPrefix(result.InterfaceResult.CommonPrefixes[j]['Prefix'])
            if (runningTask < taskNum) {
              recursiveDropByFolder({ total: 0, finished: 0, isTruncated: false, bucket: bucket, subDeleted: true }, bucket, subFolder, null, createDone(subFolder, ctx, done))
            } else {
              taskQueue.push(createRecursiveDropByFolderTask(subFolder))
            }
          }

          for (var _j = 0; _j < result.InterfaceResult.Contents.length; _j++) {
            var key = result.InterfaceResult.Contents[_j]['Key']
            doDropOne(key, ctx, done, key.lastIndexOf(delimiter) === key.length - 1)
          }

          if (ctx.isTruncated) {
            if (runningTask < taskNum) {
              recursiveDropByFolder(ctx, bucket, prefix, result.InterfaceResult.NextMarker, done)
            } else {
              taskQueue.push(function() {
                recursiveDropByFolder(ctx, bucket, prefix, result.InterfaceResult.NextMarker, done)
              })
            }
          }
        })
      }

      var folder = checkPrefix(param.Prefix)
      recursiveDropByFolder({ total: 0, finished: 0, isTruncated: false, bucket: param.Bucket, subDeleted: true }, param.Bucket, folder, null, function(ctx) {
        if (ctx.isTruncated || ctx.finished !== ctx.total) {
          return
        }

        if (ctx.subDeleted) {
          that.dropFile({
            Bucket: ctx.bucket,
            Key: folder
          }, function(err, result) {
            if (err) {
              eventCallback('dropFileFailed', folder, err)
              return _callback(err)
            }

            if (result.CommonMsg.Status >= 300) {
              eventCallback('dropFileFailed', folder, result)
              return _callback(null, result)
            }
            eventCallback('dropFileSucceed', folder, result)
            return _callback(null, result)
          })
          return
        }
        var errMessage = 'drop folder ' + folder + ' failed due to child file deletion failed'
        eventCallback('dropFileFailed', folder, new Error(errMessage))
        _callback(errMessage)
      })
    }
  }

  return posix
});

/**
 * Copyright 2019 Huawei Technologies Co.,Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
 * this file except in compliance with the License.  You may obtain a copy of the
 * License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 */
(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    define('resumable', ['md5', 'Base64'], factory)
  } else {
    root['resumable'] = factory(root['md5'], root['Base64'])
  }
})(undefined || window, function(md5, Base64) {
  var minPartSize = 100 * 1024
  var defaultPartSize = 9 * 1024 * 1024
  var maxPartSize = 5 * 1024 * 1024 * 1024

  var wrapCallback = function wrapCallback(callback, log, methodName) {
    callback = callback || function() {}
    var start = new Date().getTime()
    return function(err, result) {
      log.runLog('info', methodName, 'ObsClient cost ' + (new Date().getTime() - start) + ' ms')
      if (Object.prototype.toString.call(err) === '[object String]') {
        return callback(new Error(err), result)
      }

      return callback(err, result)
    }
  }

  var isFunction = function isFunction(obj) {
    return Object.prototype.toString.call(obj) === '[object Function]'
  }

  var wrapEventCallback = function wrapEventCallback(eventCallback) {
    eventCallback = eventCallback || function() {}
    return function(t, eventParam, result) {
      if (Object.prototype.toString.call(result) === '[object Error]') {
        return eventCallback(t, eventParam, result)
      }

      if (Object.prototype.toString.call(result) === '[object String]') {
        return eventCallback(t, eventParam, new Error(result))
      }

      if (!result) {
        return
      }

      if (result.CommonMsg.Status > 300) {
        return eventCallback(t, eventParam, new Error('status:' + result.CommonMsg.Status + ', code:' + result.CommonMsg.Code + ', message:' + result.CommonMsg.Message))
      }

      eventCallback(t, eventParam, result)
    }
  }

  var calculateUploadCheckpointMD5 = function calculateUploadCheckpointMD5(uploadCheckpoint) {
    var data = []
    data.push(uploadCheckpoint.bucket)
    data.push(uploadCheckpoint.key)
    data.push(uploadCheckpoint.sourceFile.name)
    data.push(String(uploadCheckpoint.partSize))
    data.push(String(uploadCheckpoint.partCount))
    data.push(String(uploadCheckpoint.fileStat.fileSize))
    data.push(String(uploadCheckpoint.fileStat.lastModified))

    if (uploadCheckpoint.uploadId) {
      data.push(uploadCheckpoint.uploadId)
    }

    if (uploadCheckpoint.sseC) {
      data.push(uploadCheckpoint.sseC)
    }

    if (uploadCheckpoint.sseCKey) {
      data.push(uploadCheckpoint.sseCKey)
    }

    if (uploadCheckpoint.parts) {
      for (var i = 0; i < uploadCheckpoint.parts.length; i++) {
        var part = uploadCheckpoint.parts[i]
        if (!part) {
          continue
        }
        data.push(String(part.partNumber))
        data.push(String(part.offset))
        data.push(String(part.partSize))
        data.push(String(part.isCompleted))
        if (part.etag) {
          data.push(String(part.etag))
        }
      }
    }
    return window.btoa(md5.MD5(data.join(''), false, true))
  }

  var abortRequest = function abortRequest(uploadCheckpoint, funcName, that) {
    if (uploadCheckpoint && uploadCheckpoint.uploadId) {
      that.abortMultipartUpload({
        Bucket: uploadCheckpoint.bucket,
        Key: uploadCheckpoint.key,
        RequestDate: uploadCheckpoint.requestDate,
        UploadId: uploadCheckpoint.uploadId
      }, function(err, result) {
        if (err) {
          that.log.runLog('warn', funcName, 'abort multipart upload failed, bucket:' + uploadCheckpoint.bucket + ', key:' + uploadCheckpoint.key + ', uploadId:' + uploadCheckpoint.uploadId + ', err:' + err)
          return
        }
        if (result.CommonMsg.Status >= 300) {
          that.log.runLog('warn', funcName, 'abort multipart upload failed, bucket:' + uploadCheckpoint.bucket + ', key:' + uploadCheckpoint.key + ', uploadId:' + uploadCheckpoint.uploadId + ', status:' + result.CommonMsg.Status + ', code:' + result.CommonMsg.Code + ', message:' + result.CommonMsg.Message)
          return
        }
        delete uploadCheckpoint.uploadId
        that.log.runLog('warn', funcName, 'abort multipart upload succeed, bucket:' + uploadCheckpoint.bucket + ', key:' + uploadCheckpoint.key + ', uploadId:' + uploadCheckpoint.uploadId)
      })
    }
  }

  var completedRequest = function completedRequest(ctx) {
    if (ctx.finishedCount < ctx.uploadCheckpoint.partCount) {
      return
    }

    if (ctx.isAbort) {
      abortRequest(ctx.uploadCheckpoint, ctx.funcName, ctx.that)
      return ctx.callback('uploadFile failed the upload task is aborted')
    }

    if (ctx.isSuspend) {
      return ctx.callback('the process of uploadFile is suspened, you can retry with the uploadCheckpoint')
    }

    if (ctx.hasError) {
      return ctx.callback('uploadFile finished with error, you can retry with the uploadCheckpoint')
    }

    var parts = []
    for (var i = 0; i < ctx.uploadCheckpoint.partCount; i++) {
      var part = ctx.uploadCheckpoint.parts[i]
      parts.push({
        PartNumber: part.partNumber,
        ETag: part.etag
      })
    }

    ctx.that.completeMultipartUpload({
      Bucket: ctx.uploadCheckpoint.bucket,
      Key: ctx.uploadCheckpoint.key,
      RequestDate: ctx.uploadCheckpoint.requestDate,
      UploadId: ctx.uploadCheckpoint.uploadId,
      Parts: parts
    }, function(err, result) {
      var eventParam = { bucket: ctx.uploadCheckpoint.bucket, key: ctx.uploadCheckpoint.key, uploadId: ctx.uploadCheckpoint.uploadId }
      if (err) {
        ctx.eventCallback('completeMultipartUploadFailed', eventParam, err)
        return ctx.callback(err)
      }

      if (result.CommonMsg.Status >= 500) {
        ctx.eventCallback('completeMultipartUploadFailed', eventParam, result)
        return ctx.callback(null, result)
      }

      if (result.CommonMsg.Status >= 300 && result.CommonMsg.Status < 500) {
        ctx.eventCallback('completeMultipartUploadAborted', eventParam, result)
        abortRequest(ctx.uploadCheckpoint, ctx.funcName, ctx.that)
        return ctx.callback(null, result)
      }

      ctx.eventCallback('completeMultipartUploadSucceed', eventParam, result)
      ctx.callback(null, result)
    })
  }

  var startToUploadFile = function startToUploadFile(ctx) {
    ctx.resumeCallback({
      cancel: function cancel() {
        ctx.isSuspend = true
        for (var i = 0; i < ctx.uploadPartParams.length; i++) {
          var cancelHook = ctx.uploadPartParams[i].cancelHook
          if (isFunction(cancelHook)) {
            cancelHook()
          }
        }
      }
    }, ctx.uploadCheckpoint)

    var taskQueue = []
    var doNext = function doNext() {
      while (ctx.runningTask < ctx.taskNum && taskQueue.length > 0) {
        taskQueue.shift()()
      }
      if (taskQueue.length === 0) {
        completedRequest(ctx)
      }
    }

    var createProgressCallbackByPartNumber = function createProgressCallbackByPartNumber(partNumber) {
      return function(loaded, total, cost) {
        ctx.progressCallback(partNumber, loaded)
      }
    }

    var sliceBlob = function sliceBlob(blob, start, end, type) {
      type = type || blob.type
      if (blob.mozSlice) {
        return blob.mozSlice(start, end, type)
      }
      if (blob.webkitSlice) {
        return blob.webkitSlice(start, end, type)
      }
      return blob.slice(start, end, type)
    }

    var encodeFunc = window.btoa ? window.btoa : Base64.encode

    var transArrayBufferToBinaryString = function transArrayBufferToBinaryString(buf) {
      var readSize = 16 * 1024
      buf = new Uint8Array(buf)
      var start = 0
      var data = void 0
      while (start < buf.length) {
        var end = start + readSize
        end = end <= buf.length ? end : buf.length
        if (!data) {
          data = String.fromCharCode.apply(null, buf.slice(start, end))
        } else {
          data += String.fromCharCode.apply(null, buf.slice(start, end))
        }
        start = end
      }
      buf = null
      return data
    }

    var createUploadPartTask = function createUploadPartTask(part) {
      return function() {
        ctx.runningTask++
        if (ctx.isSuspend || ctx.isAbort) {
          ctx.runningTask--
          ctx.finishedCount++
          ctx.finishedCount += taskQueue.length
          taskQueue = []
          return doNext()
        }
        var started = 0
        var doUploadPart = function doUploadPart(contentMd5) {
          if (started) {
            return
          }
          started = 1
          var uploadPartParam = {
            Bucket: ctx.uploadCheckpoint.bucket,
            Key: ctx.uploadCheckpoint.key,
            RequestDate: ctx.uploadCheckpoint.requestDate,
            PartNumber: part.partNumber,
            UploadId: ctx.uploadCheckpoint.uploadId,
            SourceFile: ctx.uploadCheckpoint.sourceFile,
            Offset: part.offset,
            PartSize: part.partSize,
            SseC: ctx.uploadCheckpoint.sseC,
            SseCKey: ctx.uploadCheckpoint.sseCKey,
            ProgressCallback: createProgressCallbackByPartNumber(part.partNumber),
            ContentMD5: contentMd5
          }
          ctx.uploadPartParams.push(uploadPartParam)

          ctx.that.uploadPart(uploadPartParam, function(err, result) {
            ctx.runningTask--
            ctx.finishedCount++
            if (ctx.isSuspend) {
              return doNext()
            }

            var eventParam = { partNumber: part.partNumber, bucket: ctx.uploadCheckpoint.bucket, key: ctx.uploadCheckpoint.key, uploadId: ctx.uploadCheckpoint.uploadId }
            if (err) {
              ctx.eventCallback('uploadPartFailed', eventParam, err)
              ctx.hasError = true
            } else if (result.CommonMsg.Status >= 500 || result.CommonMsg.Status === 400 && result.CommonMsg.Code === 'BadDigest') {
              ctx.eventCallback('uploadPartFailed', eventParam, result)
              ctx.hasError = true
            } else if (result.CommonMsg.Status >= 300 && result.CommonMsg.Status < 500) {
              ctx.isAbort = true
              ctx.hasError = true
              ctx.eventCallback('uploadPartAborted', eventParam, result)
            } else {
              part.etag = result.InterfaceResult.ETag
              part.isCompleted = true
              eventParam.etag = part.etag
              ctx.uploadCheckpoint.md5 = calculateUploadCheckpointMD5(ctx.uploadCheckpoint)
              ctx.eventCallback('uploadPartSucceed', eventParam, result)
              ctx.that.log.runLog('debug', ctx.funcName, 'Part ' + String(part.partNumber) + ' is finished, uploadId ' + ctx.uploadCheckpoint.uploadId)
            }
            doNext()
          })
        }

        if (ctx.verifyMd5 && window.FileReader && (ctx.uploadCheckpoint.sourceFile instanceof window.File || ctx.uploadCheckpoint.sourceFile instanceof window.Blob)) {
          var _sourceFile = sliceBlob(ctx.uploadCheckpoint.sourceFile, part.offset, part.offset + part.partSize)
          var fr = new window.FileReader()
          fr.onload = function(e) {
            var data = transArrayBufferToBinaryString(e.target.result)
            var contentMd5 = encodeFunc(md5.RawMD5(data, false, true))
            data = null
            doUploadPart(contentMd5)
          }

          fr.onerror = function(ex) {
            ctx.that.log.runLog('error', ctx.funcName, 'Caculate md5 for part ' + String(part.partNumber) + ' failed')
            doUploadPart()
          }
          fr.readAsArrayBuffer(_sourceFile)
          return
        }

        doUploadPart()
      }
    }

    if (!ctx.isSuspend) {
      for (var i = 0; i < ctx.uploadCheckpoint.partCount; i++) {
        var part = ctx.uploadCheckpoint.parts[i]
        if (part.isCompleted) {
          ctx.finishedCount++
          ctx.finishedBytes += part.partSize
        } else {
          taskQueue.push(createUploadPartTask(part))
        }
      }
      if (taskQueue.length === 0) {
        return completedRequest(ctx)
      }
      return doNext()
    }
    ctx.callback('the process of uploadFile is suspened, you can retry with the uploadCheckpoint')
  }

  var resumable = {}
  resumable.extend = function(ObsClient) {
    ObsClient.prototype.uploadFile = function(param, callback) {
      var that = this
      param = param || {}
      var funcName = 'uploadFile'
      var _callback = wrapCallback(callback, that.log, funcName)
      var eventCallback = wrapEventCallback(param.EventCallback)
      var taskNum = param.TaskNum || 1
      var progressCallback = param.ProgressCallback || function() {}
      var resumeCallback = param.ResumeCallback || function() {}
      var verifyMd5 = param.VerifyMd5 || false

      that.log.runLog('info', funcName, 'enter ' + funcName + '...')

      var uploadCheckpoint = null
      if (param.UploadCheckpoint && param.UploadCheckpoint.sourceFile && param.UploadCheckpoint.fileStat && param.UploadCheckpoint.uploadId && param.UploadCheckpoint.md5 === calculateUploadCheckpointMD5(param.UploadCheckpoint)) {
        uploadCheckpoint = param.UploadCheckpoint
      } else {
        abortRequest(param.UploadCheckpoint, funcName, that)
      }

      if (!uploadCheckpoint) {
        var sourceFile = param.SourceFile
        if (!(sourceFile instanceof window.File) && !(sourceFile instanceof window.Blob)) {
          return _callback('source file is not valid, must be an instanceof [File | Blob]')
        }

        if (!sourceFile.mozSlice && !sourceFile.webkitSlice && !sourceFile.slice) {
          return _callback('your browser cannot support the slice method for [File | Blob]')
        }

        that.log.runLog('debug', funcName, 'Begin to uploadFile to OBS from file:' + sourceFile.name)

        var fileSize = sourceFile.size
        var partSize = parseInt(param.PartSize, 10)
        var partCount = 0

        var parts = []
        if (fileSize === 0) {
          partSize = 0
          partCount = 1
          parts.push({ partNumber: 1, offset: 0, partSize: 0, isCompleted: false })
        } else {
          partSize = isNaN(partSize) ? defaultPartSize : partSize < minPartSize ? defaultPartSize : partSize > maxPartSize ? maxPartSize : partSize
          partCount = Math.floor(fileSize / partSize)
          if (partCount >= 10000) {
            partSize = Math.floor(fileSize / 10000)
            if (fileSize % 10000 !== 0) {
              partSize += 1
            }
            partCount = Math.floor(fileSize / partSize)
          }

          if (partSize > maxPartSize) {
            return _callback('The source file ' + sourceFile.name + ' is too large')
          }

          var lastPartSize = fileSize % partSize
          if (lastPartSize !== 0) {
            partCount++
          }

          for (var i = 0; i < partCount; i++) {
            parts.push({
              partNumber: i + 1,
              offset: i * partSize,
              partSize: partSize,
              isCompleted: false
            })
          }
          if (lastPartSize !== 0) {
            parts[partCount - 1].partSize = lastPartSize
          }
        }

        that.log.runLog('debug', funcName, 'Total parts count ' + partCount)

        uploadCheckpoint = { bucket: param.Bucket, key: param.Key, sourceFile: sourceFile, partSize: partSize, partCount: partCount, parts: parts }
        uploadCheckpoint.fileStat = {
          fileSize: fileSize,
          lastModified: sourceFile.lastModified
        }

        if (param.SseC && param.SseCKey) {
          uploadCheckpoint.sseC = param.SseC
          uploadCheckpoint.sseCKey = param.SseCKey
        }

        uploadCheckpoint.md5 = calculateUploadCheckpointMD5(uploadCheckpoint)
      } else {
        var _sourceFile2 = uploadCheckpoint.sourceFile
        if (!(_sourceFile2 instanceof window.File) && !(_sourceFile2 instanceof window.Blob)) {
          return _callback('source file is not valid, must be an instanceof [File | Blob]')
        }

        if (!_sourceFile2.mozSlice && !_sourceFile2.webkitSlice && !_sourceFile2.slice) {
          return _callback('your browser cannot support the slice method for [File | Blob]')
        }
      }

      uploadCheckpoint.requestDate = param.RequestDate

      var ctx = {
        start: new Date().getTime(),
        uploadCheckpoint: uploadCheckpoint,
        funcName: funcName,
        taskNum: taskNum,
        callback: _callback,
        that: that,
        runningTask: 0,
        finishedCount: 0,
        hasError: false,
        finishedBytes: 0,
        isAbort: false,
        resumeCallback: resumeCallback,
        isSuspend: false,
        partsLoaded: {},
        requestDate: param.RequestDate,
        uploadPartParams: [],
        verifyMd5: verifyMd5
      }

      ctx.eventCallback = function(t, eventParam, result) {
        if (ctx.isSuspend) {
          return
        }
        eventCallback(t, eventParam, result)
      }

      ctx.progressCallback = function(partNumber, loaded) {
        if (ctx.isSuspend) {
          return
        }
        ctx.finishedBytes += loaded
        if (ctx.partsLoaded[partNumber]) {
          ctx.finishedBytes -= ctx.partsLoaded[partNumber]
        }
        ctx.partsLoaded[partNumber] = loaded
        progressCallback(ctx.finishedBytes, ctx.uploadCheckpoint.fileStat.fileSize, (new Date().getTime() - ctx.start) / 1000)
      }

      if (!uploadCheckpoint.uploadId) {
        var contentType = param.ContentType
        if (!contentType && uploadCheckpoint.key) {
          contentType = that.util.mimeTypes[uploadCheckpoint.key.substring(uploadCheckpoint.key.lastIndexOf('.') + 1)]
        }

        if (!contentType && uploadCheckpoint.sourceFile.name) {
          contentType = that.util.mimeTypes[uploadCheckpoint.sourceFile.name.substring(uploadCheckpoint.sourceFile.name.lastIndexOf('.') + 1)]
        }

        that.initiateMultipartUpload({
          Bucket: param.Bucket,
          Key: param.Key,
          RequestDate: param.RequestDate,
          ACL: param.ACL,
          Metadata: param.Metadata,
          WebsiteRedirectLocation: param.WebsiteRedirectLocation,
          StorageClass: param.StorageClass,
          ContentType: contentType,
          Expires: param.Expires,
          SseKms: param.SseKms,
          SseKmsKey: param.SseKmsKey,
          SseC: param.SseC,
          SseCKey: param.SseCKey
        }, function(err, result) {
          var eventParam = { bucket: param.Bucket, key: param.Key }
          if (err) {
            ctx.eventCallback('initiateMultipartUploadFailed', eventParam, err)
            return _callback(err)
          }

          if (result.CommonMsg.Status >= 300) {
            ctx.eventCallback('initiateMultipartUploadFailed', eventParam, result)
            return _callback(null, result)
          }
          var uploadId = result.InterfaceResult.UploadId
          uploadCheckpoint.uploadId = uploadId
          uploadCheckpoint.md5 = calculateUploadCheckpointMD5(uploadCheckpoint)
          ctx.uploadCheckpoint = uploadCheckpoint

          eventParam.uploadId = uploadId
          that.log.runLog('info', funcName, 'Claim a new upload id ' + uploadId)
          ctx.eventCallback('initiateMultipartUploadSucceed', eventParam, result)
          startToUploadFile(ctx)
        })
        return
      }
      startToUploadFile(ctx)
    }
  }
  return resumable
});

/**
 * Copyright 2019 Huawei Technologies Co.,Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
 * this file except in compliance with the License.  You may obtain a copy of the
 * License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 */

(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    define('ObsClient', ['utils', 'log', 'enums', 'posix', 'resumable'], factory)
  } else {
    root['obs'] = factory(root['utils'], root['log'], root['enums'], root['posix'], root['resumable'])
    root['ObsClient'] = root['obs']
  }
})(undefined || window, function(Utils, LogUtil, enums, posix, resumable) {
  function ObsClient(param) {
    this.factory(param)
  }

  function capitalize(key) {
    return key.slice(0, 1).toUpperCase() + key.slice(1)
  }

  var methods = ['createBucket', 'listBuckets', 'getBucketMetadata', 'headBucket', 'deleteBucket', 'setBucketQuota', 'getBucketQuota', 'getBucketStorageInfo', 'setBucketPolicy', 'getBucketPolicy', 'deleteBucketPolicy', 'setBucketVersioningConfiguration', 'getBucketVersioningConfiguration', 'putBackToSource', 'deleteBackToSource', 'getBackToSource', 'getBucketLocation', 'listVersions', 'listObjects', 'setBucketLifecycleConfiguration', 'getBucketLifecycleConfiguration', 'deleteBucketLifecycleConfiguration', 'setBucketAcl', 'getBucketAcl', 'setBucketLoggingConfiguration', 'getBucketLoggingConfiguration', 'setBucketWebsiteConfiguration', 'getBucketWebsiteConfiguration', 'deleteBucketWebsiteConfiguration', 'setBucketNotification', 'getBucketNotification', 'setBucketTagging', 'getBucketTagging', 'deleteBucketTagging', 'getBucketCors', 'deleteBucketCors', 'setBucketStoragePolicy', 'getBucketStoragePolicy', 'getObject', 'getObjectMetadata', 'setObjectMetadata', 'setObjectAcl', 'getObjectAcl', 'deleteObject', 'deleteObjects', 'listMultipartUploads', 'listParts', 'abortMultipartUpload', 'completeMultipartUpload', 'getBucketInventory', 'setBucketInventory', 'deleteBucketInventory', 'getBucketEncryption', 'setBucketEncryption', 'deleteBucketEncryption', 'getBucketRequesterPay', 'setBucketRequesterPay', 'setMirrorBackToSource', 'getMirrorBackToSource', 'deleteMirrorBackToSource', 'getWorkflowTrigger', 'deleteWorkflowTrigger', 'createWorkflowTrigger', 'restoreFailedWorkflowExecution', 'createTemplate', 'createWorkflow', 'getWorkflowList', 'deleteWorkflow', 'getWorkflowTemplateList', 'getWorkflowInstanceList', 'deleteTemplate', 'updateWorkflow', 'getActionTemplates', 'getWorkflowAuthorization', 'openWorkflowAuthorization', 'getBucketDirectColdAccess', 'setBucketDirectColdAccess', 'deleteBucketDirectColdAccess', 'getBucketCustomDomain', 'setBucketCustomDomain', 'deleteBucketCustomDomain', 'setBucketCors', 'getBucketReplication', 'setBucketReplication', 'deleteBucketReplication', 'getCDNNotifyConfiguration', 'setCdnNotifyConfiguration', 'getQuota', 'getBucketDisPolicy', 'setBucketDisPolicy', 'deleteBucketDisPolicy', 'createOnlineDecom', 'getOnlineDecom', 'deleteOnlineDecom', 'setSFSAcl', 'getSFSAcl', 'deleteSFSAcl']

  function createAction(method) {
    return function(param, callback) {
      this.exec(capitalize(method), param, callback)
    }
  }

  for (var i = 0; i < methods.length; i++) {
    var method = methods[i]
    ObsClient.prototype[method] = createAction(method)
  }

  ObsClient.prototype.createTemplate = function(param, callback) {
    param.ApiPath = 'v2/workflowtemplates'
    this.exec('CreateTemplate', param, callback)
  }

  ObsClient.prototype.createWorkflow = function(param, callback) {
    param.ApiPath = 'v2/workflows'
    this.exec('CreateWorkflow', param, callback)
  }

  ObsClient.prototype.restoreFailedWorkflowExecution = function(param, callback) {
    param.ApiPath = 'v2/workflowexecutions'
    this.exec('RestoreFailedWorkflowExecution', param, callback)
  }

  ObsClient.prototype.getWorkflowList = function(param, callback) {
    param.ApiPath = 'v2/workflows'
    this.exec('GetWorkflowList', param, callback)
  }

  ObsClient.prototype.deleteWorkflow = function(param, callback) {
    param.ApiPath = 'v2/workflows'
    this.exec('DeleteWorkflow', param, callback)
  }

  ObsClient.prototype.deleteTemplate = function(param, callback) {
    param.ApiPath = 'v2/workflowtemplates'
    this.exec('DeleteTemplate', param, callback)
  }

  ObsClient.prototype.getWorkflowTemplateList = function(param, callback) {
    param.ApiPath = 'v2/workflowtemplates'
    this.exec('GetWorkflowTemplateList', param, callback)
  }

  ObsClient.prototype.getWorkflowInstanceList = function(param, callback) {
    param.ApiPath = 'v2/workflowexecutions'
    this.exec('GetWorkflowInstanceList', param, callback)
  }

  ObsClient.prototype.updateWorkflow = function(param, callback) {
    param.ApiPath = 'v2/workflows'
    this.exec('UpdateWorkflow', param, callback)
  }

  ObsClient.prototype.getActionTemplates = function(param, callback) {
    param.ApiPath = 'v2/actiontemplates'
    this.exec('GetActionTemplates', param, callback)
  }

  ObsClient.prototype.getWorkflowAuthorization = function(param, callback) {
    param.ApiPath = 'v2/workflow-authorization'
    this.exec('GetWorkflowAuthorization', param, callback)
  }
  ObsClient.prototype.openWorkflowAuthorization = function(param, callback) {
    param.ApiPath = 'v2/workflow-authorization'
    this.exec('OpenWorkflowAuthorization', param, callback)
  }

  ObsClient.prototype.putObject = function(param, callback) {
    if ('Body' in param && 'SourceFile' in param) {
      var err = 'the input body and sourcefile exist at same time,please specify one of eigther a string or file to be send!'
      this.log.runLog('error', 'PutObject', err)
      return callback(new Error(err), null)
    }

    if (!('ContentType' in param)) {
      if ('Key' in param) {
        param.ContentType = this.util.mimeTypes[param.Key.substring(param.Key.lastIndexOf('.') + 1)]
      }

      if (!param.ContentType && 'SourceFile' in param) {
        var fileName = param.SourceFile.name
        param.ContentType = this.util.mimeTypes[fileName.substring(fileName.lastIndexOf('.') + 1)]
      }
    }

    this.exec('PutObject', param, callback)
  }

  ObsClient.prototype.appendObject = function(param, callback) {
    if ('Body' in param && 'SourceFile' in param) {
      var err = 'the input body and sourcefile exist at same time,please specify one of eigther a string or file to be send!'
      if (this.log.isLevelEnabled('error')) {
        this.log.runLog('error', 'PutObject', err)
      }
      return callback(new Error(err), null)
    }

    if (!('ContentType' in param)) {
      if ('Key' in param) {
        param.ContentType = this.util.mimeTypes[param.Key.substring(param.Key.lastIndexOf('.') + 1)]
      }
      if (!param.ContentType && 'SourceFile' in param) {
        param.ContentType = this.util.mimeTypes[param.SourceFile.substring(param.SourceFile.lastIndexOf('.') + 1)]
      }
    }

    this.exec('AppendObject', param, callback)
  }

  ObsClient.prototype.copyObject = function(param, callback) {
    var key = 'CopySource'
    if (key in param) {
      var val = param[key]
      var index = val.lastIndexOf('?versionId=')
      if (index > 0) {
        param[key] = this.util.encodeURIWithSafe(val.slice(0, index)) + val.slice(index)
      } else {
        param[key] = this.util.encodeURIWithSafe(val)
      }
    }
    this.exec('CopyObject', param, callback)
  }

  ObsClient.prototype.copyPart = function(param, callback) {
    var key = 'CopySource'
    if (key in param) {
      var val = param[key]
      var index = val.lastIndexOf('?versionId=')
      if (index > 0) {
        param[key] = this.util.encodeURIWithSafe(val.slice(0, index)) + val.slice(index)
      } else {
        param[key] = this.util.encodeURIWithSafe(val)
      }
    }
    this.exec('CopyPart', param, callback)
  }

  ObsClient.prototype.restoreObject = function(param, callback) {
    this.exec('RestoreObject', param, function(err, result) {
      if (!err && result.InterfaceResult && result.CommonMsg.Status < 300) {
        result.InterfaceResult.RestoreStatus = result.CommonMsg.Status === 200 ? 'AVALIABLE' : 'INPROGRESS'
      }
      callback(err, result)
    })
  }

  ObsClient.prototype.initiateMultipartUpload = function(param, callback) {
    if (!('ContentType' in param)) {
      if ('Key' in param) {
        param.ContentType = this.util.mimeTypes[param.Key.substring(param.Key.lastIndexOf('.') + 1)]
      }
    }
    this.exec('InitiateMultipartUpload', param, callback)
  }

  ObsClient.prototype.uploadPart = function(param, callback) {
    if ('Body' in param && 'SourceFile' in param) {
      var err = 'the input body and sourcefile exist at same time, please specify one of eigther a string or file to be send!'
      this.log.runLog('error', 'UploadPart', err)
      return callback(new Error(err), null)
    }
    this.exec('UploadPart', param, callback)
  }

  posix.extend(ObsClient)
  resumable.extend(ObsClient)

  function isFunction(obj) {
    return Object.prototype.toString.call(obj) === '[object Function]'
  }

  function createPromise(current) {
    return function(param, callback) {
      if (isFunction(param)) {
        current.call(this, null, param)
        return
      }
      if (isFunction(callback)) {
        current.call(this, param, callback)
        return
      }

      var that = this
      return new Promise(function(resolve, reject) {
        current.call(that, param, function(err, result) {
          if (err) {
            return reject(err)
          }
          resolve(result)
        })
      })
    }
  }

  if (isFunction(Promise)) {
    for (var key in ObsClient.prototype) {
      if ({}.hasOwnProperty.call(ObsClient.prototype, key)) {
        var current = ObsClient.prototype[key]
        ObsClient.prototype[key] = createPromise(current)
      }
    }
  }

  ObsClient.prototype.exec = function(funcName, param, callback) {
    var _log = this.log
    _log.runLog('info', funcName, 'enter ' + funcName + '...')
    var start = new Date().getTime()
    param = param || {}
    callback = callback || function() {}
    var _callback = function _callback(err, msg) {
      if (_callback.$called) {
        return
      }
      _callback.$called = true

      if (err && !(err instanceof Error)) {
        err = new Error(err)
      }

      _log.runLog('debug', funcName, 'ObsClient cost ' + (new Date().getTime() - start) + ' ms')
      callback(err, msg)
    }
    this.util.exec(funcName, param, _callback)
  }

  ObsClient.prototype.initLog = function(param) {
    param = param || {}
    this.log.setLevel(param.level)
    var msg = ['[OBS SDK Version=' + this.util.obsSdkVersion]
    if (this.util.server) {
      var port = this.util.port ? ':' + this.util.port : ''
      msg.push('Endpoint=' + (this.util.is_secure ? 'https' : 'http') + '://' + this.util.server + port)
    }
    msg.push('Access Mode=' + (this.util.path_style ? 'Path' : 'Virtual Hosting') + ']')
    this.log.runLog('warn', 'init', msg.join('];['))
  }

  ObsClient.prototype.factory = function(param) {
    this.log = new LogUtil()
    this.util = new Utils(this.log)
    param = param || {}
    this.util.initFactory(param.access_key_id, param.secret_access_key, param.is_secure, param.server, param.path_style, param.signature, param.region, param.port, param.timeout, param.security_token, param.is_signature_negotiation, param.is_cname, param.url_prefix, param.region_domains, param.setRequestHeaderHook, param.useRawXhr)
  }

  ObsClient.prototype.refresh = function(access_key_id, secret_access_key, security_token) {
    this.util.refresh(access_key_id, secret_access_key, security_token)
  }

  ObsClient.prototype.createSignedUrlSync = function(param) {
    return this.util.createSignedUrlSync(param)
  }

  ObsClient.prototype.createV2SignedUrlSync = function(param) {
    return this.util.createV2SignedUrlSync(param)
  }

  ObsClient.prototype.createV4SignedUrlSync = function(param) {
    return this.util.createV4SignedUrlSync(param)
  }

  ObsClient.prototype.createPostSignatureSync = function(param) {
    return this.util.createPostSignatureSync(param)
  }

  ObsClient.prototype.createV4PostSignatureSync = function(param) {
    return this.util.createV4PostSignatureSync(param)
  }

  ObsClient.prototype.enums = enums

  for (var _key14 in ObsClient.prototype) {
    if ({}.hasOwnProperty.call(ObsClient.prototype, _key14)) {
      ObsClient.prototype[capitalize(_key14)] = ObsClient.prototype[_key14]
    }
  }

  for (var _key15 in ObsClient.prototype) {
    if ({}.hasOwnProperty.call(ObsClient.prototype, _key15)) {
      var index = _key15.indexOf('Configuration')
      if (index > 0 && index + 'Configuration'.length === _key15.length) {
        ObsClient.prototype[_key15.slice(0, index)] = ObsClient.prototype[_key15]
      }
    }
  }

  return ObsClient
})
